(gdb) break *0x972

Debugging, GNU± Linux and WebHosting and ... and ...

Gérard Berry : « L’ordinateur est complètement con » [Entretien Rue89]

Monday, February 02, 2015 - No comments

Extrait de l'entretien de Rue89 avec Gérad Berry du CNRS, une partie sur les bugs:

Gérard Berry est un des plus grands informaticiens français. Ancien élève de Polytechnique, il est professeur au Collège de France, membre de l’Académie des sciences et de l’Académie des technologies.

Et vous avez beaucoup travaillé sur le bug. Une question bête : comment est-il encore possible qu’il y ait des bugs ?

La question serait plutôt : comment est-il possible qu’il n’y en ait pas ?

Au départ, on a toujours la même opposition : l’homme qui va penser le programme, l’écrire et le tester. Et l’ordinateur qui va l’exécuter. L’homme est incomplet, incapable d’examiner les conséquences de ce qu’il fait. L’ordinateur, au contraire, va implémenter toutes les conséquences de ce qui est écrit. Si jamais, dans la chaîne de conséquences, il y a quelque chose qui ne devrait pas y être, l’homme ne s’en rendra pas compte, et l’ordinateur va foncer dedans. C’est ça le bug.

Un homme n’est pas capable de tirer les conséquences de ses actes à l’échelle de milliards d’instructions. Or c’est ça que va faire le programme, il va exécuter des milliards d’instructions.

Mais il existe des méthodes mathématiques, et informatisées, qui permettent de faire des calculs dont le principe est proche de celui de raisonnements humains, avec en plus les caractéristiques de l’informatique, c’est-à-dire sans aucun humour, sans aucune fatigue, et sans aucune erreur.

Understanding why Git Annex is busy with Strace

Sunday, December 21, 2014 - No comments

I'm getting into git annex for synchronizing my photos and videos between two computers and two backup disks, and sometimes commands take forever to complete. As they're not very verbose, it's try to understand what's going on:

terminal #1 $ git annex direct
commit

terminal #2 $ top
Tasks: 137 total,   2 running, 134 sleeping,   0 stopped,   1 zombie
%Cpu(s): 11.5 us,  3.8 sy,  0.0 ni, 34.7 id, 49.7 wa,  0.0 hi,  0.3 si,  0.0 st
GiB Mem :    3.830 total,    0.456 free,    0.818 used,    2.556 buff/cache
GiB Swap:    1.862 total,    1.832 free,    0.030 used.    2.711 avail Mem 

  PID USER      PR  NI    VIRT    RES  %CPU %MEM     TIME+ S COMMAND                                                                                                     
 9770 kevin     20   0 1046.6m  31.8m  21.2  0.8  66:17.35 S git

OK, our target pid is 9770 or $(pidof git) if there's only one.

$ sudo strace -p 9770
Process 9770 attached
read(4, "\32\331QJ....36\31#\327\321\361vr\246\326{y"..., 16384) = 16384
write(5, "\273\3203....\232\337\227\310\233b"..., 8192) = 8192
write(5, "F\231C\24...73<=7\34479\222\342\327\233:"..., 8192) = 8192
read(4, "M\223\36...\271\264\327\321l\260h&\36\226"..., 16384) = 16384
^C
Process 9770 detached
 <detached ...>

Git is reading from fd=4 and certainly writing it to fd=5. What are these files?

$ llh /proc/9770/fd
....
lr-x------ 1 kevin users 64 Dec 21 12:06 4 -> .../2013-03-10 Ski de rando au Grand Colon/100_0355.MP4
lrwx------ 1 kevin users 64 Dec 21 12:06 5 -> /media/sdb1/data/.git/objects/pack/tmp_pack_0vBSc4

Ok, that's why it takes time, it's copying the content of my files to git internal objects ... I'm not sure I wanted git annex to do that in fact ...

Subsidiary question: is it a good idea to let strace attached to my process, for instance to follow to progression of git annex, by tracking the files it opens?

(terminal 1) $ sudo strace -e open -p 9770
(terminal 2) $ sudo strace -e open -p $(pidof strace)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=20819, si_uid=1000, si_status=SIGTRAP, si_utime=62, si_stime=1355} ---
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
wait4(-1, [{WIFSTOPPED(s) && WSTOPSIG(s) == 133}], __WALL, NULL) = 20819
rt_sigprocmask(SIG_BLOCK, [HUP INT QUIT PIPE TERM], NULL, 8) = 0
ptrace(PTRACE_GETREGSET, 20819, NT_PRSTATUS, [{0x66a480, 216}]) = 0
ptrace(PTRACE_SYSCALL, 20819, 0, SIG_0) = 0
# and again and again

Answer: No! strace receives a ptrace notification each time the traced application does a syscall, no matter what we asked to print (-e open). And each time, strace asks for the CPU registers (PTRACE_GETREGSET). So no, don't let strace attached to your application, it will slow it down a lot!

GDB and C Preprocessor Macro

Sunday, December 21, 2014 - 3 comments

C preprocessor macro are quite convenient while programming, however they can quickly become a burden while compiling and debugging. Consider this little C program:

#define str(s) #s
#define xstr(s) str(s)

#define A 10
#define B 15

#ifndef C
#define C 15
#endif

#define MIN(x, y) (x > y ? y : x)
int printf (const char * format, ... );

void main(int argc, char **argv) {
  printf("test1 " xstr(A) " vs " xstr(B) " -> %d\n", MIN(A, B));
#undef A
#undef B
#define A 0
    printf("test2 " xstr(A) " vs " xstr(C) " -> %d\n", MIN(A, C));
}

It outputs, as expected:

$ gcc test.c && ./a.out
test1 10 vs 15 -> 10
test2 0 vs 15 -> 0
$ gcc test.c -DC=-5 && ./a.out
test1 10 vs 15 -> 10
test2 0 vs -5 -> -5

Let's add a -g in the compiler flags and see how we can follow its execution with GDB.

Debugging macros with GDB, the hard way

$ gcc test.c -DC=-5 -g && gdb ./a.out
GNU gdb (GDB) 7.8.1
Reading symbols from ./a.out...done.
(gdb) start
Starting program: /tmp/a.out
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe998) at test.c:15
15    printf("test1 " xstr(A) " vs " xstr(B) " -> %d\n", MIN(A, B));
(gdb) print A
No symbol "A" in current context.
(gdb) p B
No symbol "B" in current context.

Okay, so we can't go anywhere so easily. So let's continue the hard way:

(gdb) x/4i $pc # print 4 i-instructions after the current address of the program counter/instruction pointer $pc
=> 0x400515 <main+15>:  mov    $0xa,%esi
   0x40051a <main+20>:  mov    $0x4005c4,%edi
   0x40051f <main+25>:  mov    $0x0,%eax
   0x400524 <main+30>:  callq  0x4003e0 <printf@plt>
(gdb) p/d 0xa # print hexadecimal number 0xa in d-igits
$2 = 10
(gdb) p (char *) 0x4005c4 # cast this address in char* and print it
$3 = 0x4005c4 "test1 10 vs 15 -> %d\n"

There we are, the processor is going to execute printf("test1 10 vs 15 -> %d\n", 10). Naively I expected to see the comparison between 10 and 15, but the compiler optimizes that automatically, even with -O0 flag. Change one operand to a 'real' C variable to see the comparison in the code.

That works, but that's a bit hardcore, and not easy to apply in all the situation. Nonetheless, it can be useful for instance to see which functions(s) will be called by a preprocessor macro function.

What can we do to better understand such pieces of code ?

First, let's remember how the preprocessor works: it preprocesses the source file, before passing it to the actual C compiler.

So let's intercept this step.

Debugging macros with GCC, an easier way

GCC can dump this intermediate step with the flag -E, or directly apply cpp to your file:

$ cpp test.c -DC=-5 # OR # gcc -E test.c -DC=-5
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "test.c"
# 12 "test.c"
int printf (const char * format, ... );

void main(int argc, char **argv) {
  printf("test1 " "10" " vs " "15" " -> %d\n", (10 > 15 ? 15 : 10));
  printf("test2 " "0" " vs " "-5" " -> %d\n", (0 > -5 ? -5 : 0));
}

And there we can see what is exactly fed to the C compiler. Note that the comparison is still here, so it's (obviously) not the preprocessor which optimized it out.

But this is not very interactive ... and we said that we want to use GDB!

Debugging macros with GDB, the nice way

The lasts versions of GCC+GDB (I can't say since when it's in place, just that it works with my up-to-date Archlinux) can respectively include and interpret preprocessor macro definitions inside the binary's debugging information. It's not included in the standard -g debugging flag, but in -g3, certainly because of the quantity of information that need to be included with dozens of header files are included in a C file.

$ gcc -g3 test.c -DC=-5  && gdb a.out 
GNU gdb (GDB) 7.8.1
Reading symbols from a.out...done.
(gdb) info macro A
The symbol `A' has no definition as a C/C++ preprocessor macro
at <user-defined>:-1

Argl, what's that? all the article was a lie? all of that to come to 'A' has no definition as a C/C++ preprocessor macro? That's what I though until yesterday. I tried to play with macros in GDB a couple of time, but always failed this hard. Until I read this forum post, that says in a more polite way: RTFM!

gdb uses the current listing position to decide which macro definitions are in scope.

Oh, yes, indeed, it makes sense ... !

(gdb) start
Temporary breakpoint 1 at 0x400515: file test.c, line 15.
Starting program: /tmp/a.out 
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe998) at test.c:15
15    printf("test1 " xstr(A) " vs " xstr(B) " -> %d\n", MIN(A, B));
(gdb) info macro A
Defined at /tmp/test.c:4
#define A 10
(gdb) next
test1 10 vs 15 -> 10
19      printf("test2 " xstr(A) " vs " xstr(C) " -> %d\n", MIN(A, C));
(gdb) info macro A
Defined at /tmp/test.c:18
#define A 0
(gdb) info macro C
Defined at /tmp/test.c:0
-DC=-5
(gdb) info macro MIN
Defined at /tmp/test.c:11
#define MIN(x, y) (x > y ? y : x)

GDB can also expand macro functions:

(gdb) macro expand MIN(A, B)
expands to: (10 > 15 ? 15 : 10)
(gdb) macro expand MIN(A,  MIN(A, 15))
expands to: (10 > (10 > 15 ? 15 : 10) ? (10 > 15 ? 15 : 10) : 10)
(gdb) p (10 > (10 > 15 ? 15 : 10) ? (10 > 15 ? 15 : 10) : 10)
$1 = 10

There we are, and that's working well, cool :-) (if you run gcc -E test.c -DC=-5 -g3 you'll see that the preprocessor passes the #defines to the compiler, including the builtin ones.

However, I couldn't get macro define|list|undef to work. According to the help, GDB should be able to change the value of macro-definitions, but that seems very hard to implement, maybe that's why it doesn't work ...

(gdb) help macro define
Define a new C/C++ preprocessor macro.
The GDB command `macro define DEFINITION' is equivalent to placing a
preprocessor directive of the form `#define DEFINITION' such that the
definition is visible in all the inferior's source files.
For example:
  (gdb) macro define PI (3.1415926)
  (gdb) macro define MIN(x,y) ((x) < (y) ? (x) : (y))
(gdb) start
Temporary breakpoint 1 at 0x400515: file test.c, line 15.
Starting program: /tmp/a.out 
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe998) at test.c:15
15    printf("test1 " xstr(A) " vs " xstr(B) " -> %d\n", MIN(A, B));
(gdb) macro define A -5
(gdb) macro define B -10
(gdb) n
test1 10 vs 15 -> 10

Multiple Github Accounts and SSH Identities

Wednesday, December 17, 2014 - No comments

I have two github accounts, one for academic work and another for my personal projects. But Github identifies you by your ssh key, you commit account is nowhere written in git@github.com:perso/project.git.

Although Github staff don't advise us to have multiple account, I don't want to mix my personal work with the academic one:

Hi Kevin,

Thanks for getting in touch. I strongly recommend that you do not use multiple personal GitHub accounts. Using multiple personal accounts often leads to confusion, and is almost always unnecessary. I recommend that you consolidate your accounts into a single account.

Thanks, James Dennes (GitHub Staff)"

Solution: Multiple ssh Keys and ssh Configuration

As github identities your account with the ssh key you use for the connection, you just have to create another ssh key:

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/kevin/.ssh/id_rsa): /home/kevin/.ssh/id_rsa_perso
...

and give the public key ~/.ssh/id_rsa_perso.pub to github.

Last thing, to greatly simplify the usage of that second key, tell ssh when to use it or not:

$ cat ~/.ssh/config
Host github.perso
  HostName github.com
  User git
  IdentityFile /home/kevin/.ssh/id_rsa-perso

Now, ssh github.perso is equivalent to ssh git@github.com -i /home/kevin/.ssh/id_rsa-perso. So you can clone your personal repository simply by changing github.com to github.perso in the repository URL:

git clone `git@github.perso:perso/project.git` # or just github-perso:perso/project.git

Publié dans :

Server Monitoring with Monit

Wednesday, December 17, 2014 - No comments

Last Friday, 0x972.info's server was suspended by the host provider (PulseHeberg) because of a high CPU load for 10 minutes.

CPU Load Indicator

The CPU loads corresponds to the time the CPU is actually running code, over the time it rests. The lower the best, 1 means 100% of usage of 1 processor core, 2 for 2 cores, etc. It's computed for 1min, 5min and 10min:

(desktop) $ uptime
... load average: 0.04, 0.06, 0.17
(server) $ uptime
... load average: 0.11, 0.04, 0.01

When applications bug, they can enter infinite loop, and thus never let the CPU rest. This can be verified easily with a while loop: while [ 1 -eq 1 ] do ; echo -n "" ; done

While loop and CPU load

In the screenshot, we can see two infinite loops (to raise the load faster), and on the other side, the 1min CPU load reads 1.03. (You an also recognize my i3 desktop and custom task bar, with a visual indicator of the current load: both CPU cores are too high, and the temperature T is rising).

Overload Prevention

Suspending the server is the only safe thing the host provider can do: it's undoubtedly a failing application that caused the overload, and it would escape the infinite loop by itself, so they shutdown the enter server. But on the user side, we've got more control over the server, so there's certainly something less brutal that we can do.

And here comes monit (with a nice presentation of their website):

check process sshd with pidfile /var/run/sshd.pid
   start program  "/etc/init.d/ssh start"
   stop program  "/etc/init.d/ssh stop"
   if failed protocol ssh then restart
   if 5 restarts within 5 cycles then alert
   if 5 restarts within 5 cycles then timeout

It's almost in plain English:

  • monitor the process sshd with its PID stored in file ...,
  • you can start and stop the program this way,
  • if it fails the ssh test connection, restart it,
  • if it fails too often, send me a mail alert and stop monitoring it

Apache httpd is a bit more complex, but still straight forward to read:

check process apache with pidfile /var/run/apache2.pid
   group www
   start program = "/etc/init.d/apache2 start"
   stop  program = "/etc/init.d/apache2 stop"
   if failed host www.0x972.info port 80 
        protocol HTTP request "/monit/token" then restart
   if failed host www.0x972.info port 443 
             type TCPSSL protocol HTTP request "/monit/token" then restart
   if 5 restarts within 5 cycles then timeout
   if cpu > 40% for 2 cycles then alert
   if totalcpu > 60% for 2 cycles then alert
   if totalcpu > 80% for 5 cycles then restart
   if mem > 100 MB for 5 cycles then restart
   if loadavg(5min) greater than 1.5 for 8 cycles then stop

I configured monit to run the checks every 2 minutes, and send mails to me in case of failures.

set daemon 120
set alert kevin@...

Currently, I configured the monitoring for apache2, dovecot, mysql, postfix sshd as well as system-wide properties.

From: ...
To: ...
Subject: monit alert --  Connection failed mysql (Tue, 16 Dec 2014 16:21:15)
Date: Tue, 16 Dec 2014 15:21:15 GMT
Connection failed Service mysql
    Action:      restart
    Host:        www.0x972.info
    Description: failed protocol test [MYSQL] at INET[0x972.info:3306] via TCP -- MYSQL: error receiving login response
    Date:        Tue, 16 Dec 2014 16:21:15

Publié dans :

Would I be happy to study/debug/extend your code?

Tuesday, December 09, 2014 - No comments

(lines starting with a @ are personal feeling, the others not so much, I hope)

The higher the best, positive ranks look like quality code.

Versioning

  • Do you use a versioning system (git, svn, cvs, ...) no=-15

  • If no, will I come to work at your desk? no=-15

    • that means email file sharing ... :-(
  • @Do you use GIT? yes=+15

  • Do you commit feature by feature? yes=+20

    • git blame is documentation!

Coding Style

  • Is your code steadily indented? no=-30

    • Python devs, skip this question ;-)
  • Is your code well spaced? no=-30

    • no doubles spaces --except indentation--, no (␣ or ␣), always ␣=␣, ...
  • Are all (max 2-3) variables more than 3-letter long? no=-15

  • Do you follow the same coding convention all over your code? no=-10

  • Do you follow an official coding convention all over your code? yes=+30

Coding

  • @Is it C/Python/LaTeX code? yes=+10
  • @Is it PHP or JS code? yes=-10

  • Do you have functions with more than 30 parameters? yes=-30

  • Do your functions have in average <6 parameters? no=-15

  • Are your function bodies < one screen of LOC? no=-15

  • Can I easily spot copied-past-adapted code blocks (<3 LOC)? yes=-5 per block

  • Can I easily spot duplicated code blocks (<3 LOC)? yes=-10 per block

    • if (test){do_a;do_z}else{do_c;do_z}

System

  • @Do you use a Linux/Unix-based OS? no=-40

    • I will not be able to use most of my favorite tools!
  • [if applies] Do you have a build system (Makefile)? no=-30

  • Can you compile in an (external) build directory? yes=+20

  • Are all of your source files text-based? no=-20

    • I can't grep, diff, ... in OpenOfficeCalc for instance
  • Do you have unit tests/non regression testsuite? yes=+30

Publié dans :

HTML Trick: Second Try with Element Inspector

Tuesday, December 09, 2014 - No comments

Another example after the trick to reveal 'hidden' passwords:

In Flickr, when the author put a right restriction, Flicker disables the ability to right-click and download the image (try it here, *View background image): you end up with a 1-px blank image.

So fire up the Element Inspector, that should highlight that "protection" zone:

And just delete this tiny div! (actually, the link to the image <img src=... /> is right below).

Now View image is available again :-)

By the way, in up-to-date versions of Firefox, you can bypass right-click protection by pressing the shift key at the same time, like in this website.

Publié dans :  

[Dev-tool configuration] i3 Window Manager

Tuesday, December 09, 2014 - No comments

Since a few years, I stopped using a traditional desktop manager like Gnome or KDE (maybe when Gnome switch to version 3?). I'm now addicted to my tiling window manager, i3. I3 manages only the windows on my screen, but not the desktop. Hence, when there's no window on my screen ... it's black! That could be improved, but most of the time, I have a window, so it doesn't matter. But no clickable icon, no clickable toolbar, just windows!

A tiling window manager (WM) gives the maximum room to each window, either by tabbing them, like in firefox, or by splitting (and sub-spliting) the screen horizontally or vertically:

Caught working hard

As there are no icons or clickable toolbar, everything is done with keyboard shortcuts. The learning curve, at the beginning, is a bit steep I admit! But one you get it, it's really nice to use!

Let's dive step-by-step into my configuration file:

Mod4 is 'Windows' key

Start applications

  • Mod4+Shift is the prefix to start applications. Mod4+Control is for alternative starts

    # Application shortcuts
    set $Mod_app Mod4+Shift
    set $Mod_app_alt Mod4+Control
    
  • Common tools:

    bindsym $Mod_app+f exec firefox
    bindsym $Mod_app+t exec thunderbird
    
    bindsym $Mod_app+m exec emacsclient -c # emacsclient needs an `emacs --daemon`
    bindsym $Mod_app_alt+m exec emacs # safe start, but takes longer
    
    # Start a terminal (urxvt client)
    bindsym $Mod_app+Return exec urxvtc # needs `urxvtd`
    bindsym $Mod_app_alt+Return exec urxvt # failsafe terminal
    
  • Force floating window (I guess these window don't respect all the protocols, so they are seen as primary windows, instead of floating boxes):

    for_window [class="Nautilus" instance="file_progress"] floating enable
    for_window [class="Xmessage"] floating enable
    for_window [title="Find"] floating enable
    
  • Helpers:

    bindsym Mod4+l exec i3lock -i /home/kevin/.i3/lock.png # locks the screen with a background image
    bindsym Mod4+F2 exec dmenu_run
    
    # Kill the current window
    bindsym $Mod_app+q kill # close the current 
    

See also dmenu_run, i3lock. I'll explain urxvtc and emacsclient in another post.

Window management

  • Window layout

    # Stacking / Tabbed / Default layout
    workspace_layout tabbed
    
    bindsym Mod4+s layout stacking
    bindsym Mod4+t layout tabbed
    bindsym Mod4+d layout default
    
  • Splitting windows

    default_orientation vertical
    # Split horizonally or vertically a window
    # *I can't help but consider than vertical split means that the window split should be vertical,
    # and the sub-windows side-by-side*, so I reversed h and v
    bindsym Mod4+h split vertical
    bindsym Mod4+v split horizontal
    
  • Moving windows

    set $Mod_move Mod4+Shift
    bindsym $Mod_move+Left move left
    bindsym $Mod_move+Right move right
    bindsym $Mod_move+Down move down
    bindsym $Mod_move+Up move up
    
    bindsym Mod4+f fullscreen
    bindsym Mod4+Mod1+f fullscreen global # on all screens
    
    # Toggle tiling/floating of the current window
    bindsym $Mod_move+space floating toggle
    
  • Changing the focus

    bindsym Mod4+Left focus left
    bindsym Mod4+Right focus right
    bindsym Mod4+Down focus down
    bindsym Mod4+Up focus up
    
  • Scratchpad (=invisible place)

    bindsym F12 move scratchpad
    bindsym F11 scratchpad show
    
  • Workspaces

    bindcode $Mod_move+10 move workspace 1 # touch 1
    bindcode $Mod_move+11 move workspace 2 # code for touch n = 9+n
    ...
    bindcode $Mod_move+86 move workspace next # touch +, found with `xev`
    bindcode $Mod_move+82 move workspace prev # touch -
    
  • Window resize

    # Window resize (although mouse is more convenient!)
    mode "resize" {
      bindsym Left resize grow left 10 px
      bindsym Shift+Left resize shrink left 10 px
    
      bindsym Down resize grow down 10 px
      bindsym Shift+Down resize shrink down 10 px
    
      bindsym Up resize grow up 10 px
      bindsym Shift+Up resize shrink up 10 px
    
      bindsym Right resize grow right 10 px
      bindsym Shift+Right resize shrink right 10 px
    
      #Enter to return to default
      bindsym Return mode "default"
    }
    

Misc.

  • Sound configuration

    set $Mod_sound Mod4+Mod1 #Win+Alt
    bindsym  $Mod_sound+m  exec amixer sset Master toggle
    bindcode $Mod_sound+82 exec amixer set Master 1%- # touch +
    bindcode $Mod_sound+86 exec amixer set Master 1%+ # touch -
    
    bindsym  XF86AudioMute exec amixer sset Master toggle # laptop multimedia keys
    bindsym  XF86AudioLowerVolume exec amixer set Master 1%-
    bindsym  XF86AudioRaiseVolume exec amixer set Master 1%+
    
    exec amixer sset Master mute # set to mute after boot sequence
    
  • Keyboard map (lang) configuration

    bindsym Mod4+Ctrl+f exec setxkbmap fr
    bindsym Mod4+Ctrl+u exec setxkbmap us
    
  • Borderless window or not

    hide_edge_borders both # by default, no side borders
    bindsym Mod4+p border normal
    bindsym Mod4+o border none # includes no window title
    
  • Restart and reload i3

    set $Mod_sys Mod4+Shift+Control
    bindsym $Mod_sys+e restart
    bindsym $Mod_sys+r reload
    
  • Home-made status bar (I'll put it online and explain it later)

    bindsym Mod4+Shift+w exec ~/.i3/i3status.py --kill --ws2
    bindsym Mod4+Ctrl+w exec ~/.i3/i3status.py --kill --ws1
    bar {
        position bottom
        mode hide
    }
    exec ~/.i3/i3status.py
    

Enjoy, i3 is a great tool, especially for development with multiple screens!

[Dev-tools configuration] Git difftool

Tuesday, December 09, 2014 - No comments

By default in git, when you ask for the diff between the two commits (or the last commit and the current head, or any diff actually), it prints it in the console in a patch-compatible form:

diff --git a/capture.py b/capture.py
index 4fe884f..9fe6d0e 100644
--- a/capture.py
+++ b/capture.py
@@ -23,7 +23,8 @@ class FunctionFinishBreakpoint (gdb.Breakpoint):
     def stop(self):
         self.parent.fhit_internal += 1
         self.enabled = False
-        
+        num = gdb.selected_thread().num
+        print "{}#{} F-STOP in {}".format("|   "*(num-1), num, self.parent.__class__.__name__.replace("_", " ").replace(" Breakpoint", ""))
         fct_stop = self.parent.prepare_after(self.fct_data)

         filter_stop = self.parent.stop_after_filters(self.filter_params)

That's nice, but not necessarily the easiest way to compare two versions of a file. Instead of that, I prefer using meld and its graphical interface:

git config --global diff.tool meld
git config --global merge.tool meld
git config --global --add difftool.prompt false # don't ask for a confirmation before starting meld

Now use git difftool and git mergetool and you'll see your file comparison directly in meld! You can see the result in cat ~.gitconfig:

...
[diff]
    tool = meld
[merge]
    tool = meld
[difftool]
    prompt = false

Publié dans :