|  | # 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 | 
|  | foreach spec $tracking_branches { | 
|  | set t [lindex $spec 0] | 
|  | if {$t eq $name || [string match $t $name]} { | 
|  | return 1 | 
|  | } | 
|  | } | 
|  | return 0 | 
|  | } | 
|  |  | 
|  | proc all_tracking_branches {} { | 
|  | global tracking_branches | 
|  |  | 
|  | set all [list] | 
|  | set pat [list] | 
|  | set cmd [list] | 
|  |  | 
|  | foreach spec $tracking_branches { | 
|  | set dst [lindex $spec 0] | 
|  | if {[string range $dst end-1 end] eq {/*}} { | 
|  | lappend pat $spec | 
|  | lappend cmd [string range $dst 0 end-2] | 
|  | } else { | 
|  | lappend all $spec | 
|  | } | 
|  | } | 
|  |  | 
|  | if {$pat ne {}} { | 
|  | set fd [eval git_read for-each-ref --format=%(refname) $cmd] | 
|  | while {[gets $fd n] > 0} { | 
|  | foreach spec $pat { | 
|  | set dst [string range [lindex $spec 0] 0 end-2] | 
|  | set len [string length $dst] | 
|  | if {[string equal -length $len $dst $n]} { | 
|  | set src [string range [lindex $spec 2] 0 end-2] | 
|  | set spec [list \ | 
|  | $n \ | 
|  | [lindex $spec 1] \ | 
|  | $src[string range $n $len end] \ | 
|  | ] | 
|  | lappend all $spec | 
|  | } | 
|  | } | 
|  | } | 
|  | close $fd | 
|  | } | 
|  |  | 
|  | return [lsort -index 0 -unique $all] | 
|  | } | 
|  |  | 
|  | proc load_all_remotes {} { | 
|  | global repo_config | 
|  | global all_remotes tracking_branches some_heads_tracking | 
|  | global remote_url | 
|  |  | 
|  | set some_heads_tracking 0 | 
|  | set all_remotes [list] | 
|  | 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 \ | 
|  | -types f \ | 
|  | -tails \ | 
|  | -nocomplain \ | 
|  | -directory $rm_dir *] | 
|  |  | 
|  | foreach name $all_remotes { | 
|  | catch { | 
|  | set fd [open [file join $rm_dir $name] r] | 
|  | while {[gets $fd line] >= 0} { | 
|  | if {[regexp {^URL:[ 	]*(.+)$} $line line url]} { | 
|  | set remote_url($name) $url | 
|  | continue | 
|  | } | 
|  | if {![regexp {^Pull:[ 	]*([^:]+):(.+)$} \ | 
|  | $line line src dst]} continue | 
|  | if {[string index $src 0] eq {+}} { | 
|  | set src [string range $src 1 end] | 
|  | } | 
|  | 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 | 
|  | } | 
|  | lappend trck [list $dst $name $src] | 
|  | } | 
|  | close $fd | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | foreach line [array names repo_config remote.*.url] { | 
|  | if {![regexp ^remote\.(.*)\.url\$ $line line name]} continue | 
|  | lappend all_remotes $name | 
|  | set remote_url($name) $repo_config(remote.$name.url) | 
|  |  | 
|  | if {[catch {set fl $repo_config(remote.$name.fetch)}]} { | 
|  | set fl {} | 
|  | } | 
|  | foreach line $fl { | 
|  | if {![regexp {^([^:]+):(.+)$} $line line src dst]} continue | 
|  | if {[string index $src 0] eq {+}} { | 
|  | set src [string range $src 1 end] | 
|  | } | 
|  | 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 | 
|  | } | 
|  | lappend trck [list $dst $name $src] | 
|  | } | 
|  | } | 
|  |  | 
|  | set tracking_branches [lsort -index 0 -unique $trck] | 
|  | set all_remotes [lsort -unique $all_remotes] | 
|  | } | 
|  |  | 
|  | proc add_fetch_entry {r} { | 
|  | global repo_config | 
|  | set remote_m .mbar.remote | 
|  | set fetch_m $remote_m.fetch | 
|  | set prune_m $remote_m.prune | 
|  | set remove_m $remote_m.remove | 
|  | set enable 0 | 
|  | if {![catch {set a $repo_config(remote.$r.url)}]} { | 
|  | if {![catch {set a $repo_config(remote.$r.fetch)}]} { | 
|  | set enable 1 | 
|  | } | 
|  | } else { | 
|  | catch { | 
|  | set fd [open [gitdir remotes $r] r] | 
|  | while {[gets $fd n] >= 0} { | 
|  | if {[regexp {^Pull:[ \t]*([^:]+):} $n]} { | 
|  | set enable 1 | 
|  | break | 
|  | } | 
|  | } | 
|  | close $fd | 
|  | } | 
|  | } | 
|  |  | 
|  | if {$enable} { | 
|  | if {![winfo exists $fetch_m]} { | 
|  | menu $remove_m | 
|  | $remote_m insert 0 cascade \ | 
|  | -label [mc "Remove Remote"] \ | 
|  | -menu $remove_m | 
|  |  | 
|  | menu $prune_m | 
|  | $remote_m insert 0 cascade \ | 
|  | -label [mc "Prune from"] \ | 
|  | -menu $prune_m | 
|  |  | 
|  | menu $fetch_m | 
|  | $remote_m insert 0 cascade \ | 
|  | -label [mc "Fetch from"] \ | 
|  | -menu $fetch_m | 
|  | } | 
|  |  | 
|  | $fetch_m add command \ | 
|  | -label $r \ | 
|  | -command [list fetch_from $r] | 
|  | $prune_m add command \ | 
|  | -label $r \ | 
|  | -command [list prune_from $r] | 
|  | $remove_m add command \ | 
|  | -label $r \ | 
|  | -command [list remove_remote $r] | 
|  | } | 
|  | } | 
|  |  | 
|  | proc add_push_entry {r} { | 
|  | global repo_config | 
|  | set remote_m .mbar.remote | 
|  | set push_m $remote_m.push | 
|  | set enable 0 | 
|  | if {![catch {set a $repo_config(remote.$r.url)}]} { | 
|  | if {![catch {set a $repo_config(remote.$r.push)}]} { | 
|  | set enable 1 | 
|  | } | 
|  | } else { | 
|  | catch { | 
|  | set fd [open [gitdir remotes $r] r] | 
|  | while {[gets $fd n] >= 0} { | 
|  | if {[regexp {^Push:[ \t]*([^:]+):} $n]} { | 
|  | set enable 1 | 
|  | break | 
|  | } | 
|  | } | 
|  | close $fd | 
|  | } | 
|  | } | 
|  |  | 
|  | if {$enable} { | 
|  | if {![winfo exists $push_m]} { | 
|  | menu $push_m | 
|  | $remote_m insert 0 cascade \ | 
|  | -label [mc "Push to"] \ | 
|  | -menu $push_m | 
|  | } | 
|  |  | 
|  | $push_m add command \ | 
|  | -label $r \ | 
|  | -command [list push_to $r] | 
|  | } | 
|  | } | 
|  |  | 
|  | proc populate_remotes_menu {} { | 
|  | global all_remotes | 
|  |  | 
|  | foreach r $all_remotes { | 
|  | add_fetch_entry $r | 
|  | add_push_entry $r | 
|  | } | 
|  | } | 
|  |  | 
|  | proc add_single_remote {name location} { | 
|  | global all_remotes repo_config | 
|  | lappend all_remotes $name | 
|  |  | 
|  | git remote add $name $location | 
|  |  | 
|  | # XXX: Better re-read the config so that we will never get out | 
|  | # of sync with git remote implementation? | 
|  | set repo_config(remote.$name.url) $location | 
|  | set repo_config(remote.$name.fetch) "+refs/heads/*:refs/remotes/$name/*" | 
|  |  | 
|  | add_fetch_entry $name | 
|  | add_push_entry $name | 
|  | } | 
|  |  | 
|  | proc delete_from_menu {menu name} { | 
|  | if {[winfo exists $menu]} { | 
|  | $menu delete $name | 
|  | } | 
|  | } | 
|  |  | 
|  | proc remove_remote {name} { | 
|  | global all_remotes repo_config | 
|  |  | 
|  | git remote rm $name | 
|  |  | 
|  | catch { | 
|  | # Missing values are ok | 
|  | unset repo_config(remote.$name.url) | 
|  | unset repo_config(remote.$name.fetch) | 
|  | unset repo_config(remote.$name.push) | 
|  | } | 
|  |  | 
|  | set i [lsearch -exact all_remotes $name] | 
|  | lreplace all_remotes $i $i | 
|  |  | 
|  | set remote_m .mbar.remote | 
|  | delete_from_menu $remote_m.fetch $name | 
|  | delete_from_menu $remote_m.prune $name | 
|  | delete_from_menu $remote_m.remove $name | 
|  | # Not all remotes are in the push menu | 
|  | catch { delete_from_menu $remote_m.push $name } | 
|  | } |