git-gui: Optimize for newstyle refs/remotes layout
authorShawn O. Pearce <spearce@spearce.org>
Wed, 4 Jul 2007 04:15:41 +0000 (00:15 -0400)
committerShawn O. Pearce <spearce@spearce.org>
Mon, 9 Jul 2007 01:12:48 +0000 (21:12 -0400)
Most people using Git 1.5.x and later are using the newer style
of remotes layout where all of their tracking branches are in
refs/remotes and refs/heads contains only the user's own local
branches.

In such a situation we can avoid calling is_tracking_branch
for each head we are considering because we know that all of
the heads must be local branches if no fetch option or Pull:
line maps a branch into that namespace.

If however any remote maps a remote branch into a local
tracking branch that resides in refs/heads we do exactly
what we did before, which requires scanning through all
fetch lines in case any patterns are matched.

I also switched some regexp/regsub calls to string match
as this can be a faster operation for prefix matching.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
lib/branch.tcl
lib/remote.tcl

index e56f674c6dc3348d9ee9e23e8424947fa4a321e7..de638d02e8023636e4198d5546e1eb3ac6f6ab32 100644 (file)
@@ -3,13 +3,16 @@
 
 proc load_all_heads {} {
        global all_heads
+       global some_heads_tracking
 
+       set rh refs/heads
+       set rh_len [expr {[string length $rh] + 1}]
        set all_heads [list]
-       set fd [open "| git for-each-ref --format=%(refname) refs/heads" r]
+       set fd [open "| git for-each-ref --format=%(refname) $rh" r]
        while {[gets $fd line] > 0} {
-               if {[is_tracking_branch $line]} continue
-               if {![regsub ^refs/heads/ $line {} name]} continue
-               lappend all_heads $name
+               if {!$some_heads_tracking || ![is_tracking_branch $line]} {
+                       lappend all_heads [string range $line $rh_len end]
+               }
        }
        close $fd
 
index b54824ab725d9f11c6c5a38a8e0c53f37e41adc5..55a6dc33011701902f12c9af575074808bbcbcba 100644 (file)
@@ -1,14 +1,13 @@
 # git-gui remote management
 # Copyright (C) 2006, 2007 Shawn Pearce
 
+set some_heads_tracking 0;  # assume not
+
 proc is_tracking_branch {name} {
        global tracking_branches
-
-       if {![catch {set info $tracking_branches($name)}]} {
-               return 1
-       }
-       foreach t [array names tracking_branches] {
-               if {[string match {*/\*} $t] && [string match $t $name]} {
+       foreach spec $tracking_branches {
+               set t [lindex $spec 0]
+               if {$t eq $name || [string match $t $name]} {
                        return 1
                }
        }
@@ -20,9 +19,10 @@ proc all_tracking_branches {} {
 
        set all_trackings {}
        set cmd {}
-       foreach name [array names tracking_branches] {
-               if {[regsub {/\*$} $name {} name]} {
-                       lappend cmd $name
+       foreach spec $tracking_branches {
+               set name [lindex $spec 0]
+               if {[string range $name end-1 end] eq {/*}} {
+                       lappend cmd [string range $name 0 end-2]
                } else {
                        regsub ^refs/(heads|remotes)/ $name {} name
                        lappend all_trackings $name
@@ -43,11 +43,14 @@ proc all_tracking_branches {} {
 
 proc load_all_remotes {} {
        global repo_config
-       global all_remotes tracking_branches
+       global all_remotes tracking_branches some_heads_tracking
 
+       set some_heads_tracking 0
        set all_remotes [list]
-       array unset tracking_branches
+       set trck [list]
 
+       set rh_str refs/heads/
+       set rh_len [string length $rh_str]
        set rm_dir [gitdir remotes]
        if {[file isdirectory $rm_dir]} {
                set all_remotes [glob \
@@ -62,10 +65,16 @@ proc load_all_remotes {} {
                                while {[gets $fd line] >= 0} {
                                        if {![regexp {^Pull:[   ]*([^:]+):(.+)$} \
                                                $line line src dst]} continue
-                                       if {![regexp ^refs/ $dst]} {
-                                               set dst "refs/heads/$dst"
+                                       if {![string equal -length 5 refs/ $src]} {
+                                               set src $rh_str$src
+                                       }
+                                       if {![string equal -length 5 refs/ $dst]} {
+                                               set dst $rh_str$dst
                                        }
-                                       set tracking_branches($dst) [list $name $src]
+                                       if {[string equal -length $rh_len $rh_str $dst]} {
+                                               set some_heads_tracking 1
+                                       }
+                                       lappend trck [list $dst $name $src]
                                }
                                close $fd
                        }
@@ -81,13 +90,20 @@ proc load_all_remotes {} {
                }
                foreach line $fl {
                        if {![regexp {^([^:]+):(.+)$} $line line src dst]} continue
-                       if {![regexp ^refs/ $dst]} {
-                               set dst "refs/heads/$dst"
+                       if {![string equal -length 5 refs/ $src]} {
+                               set src $rh_str$src
+                       }
+                       if {![string equal -length 5 refs/ $dst]} {
+                               set dst $rh_str$dst
+                       }
+                       if {[string equal -length $rh_len $rh_str $dst]} {
+                               set some_heads_tracking 1
                        }
-                       set tracking_branches($dst) [list $name $src]
+                       lappend trck [list $dst $name $src]
                }
        }
 
+       set tracking_branches [lsort -index 0 -unique $trck]
        set all_remotes [lsort -unique $all_remotes]
 }