1# git-gui remote management2# Copyright (C) 2006, 2007 Shawn Pearce34set some_heads_tracking 0; # assume not56proc is_tracking_branch {name} {7global tracking_branches8foreach spec $tracking_branches {9set t [lindex $spec 0]10if {$t eq $name || [string match $t $name]} {11return 112}13}14return 015}1617proc all_tracking_branches {} {18global tracking_branches1920set all [list]21set pat [list]22set cmd [list]2324foreach spec $tracking_branches {25set dst [lindex $spec 0]26if {[string range $dst end-1 end] eq {/*}} {27lappend pat $spec28lappend cmd [string range $dst 0 end-2]29} else {30lappend all $spec31}32}3334if {$pat ne {}} {35set fd [eval git_read for-each-ref --format=%(refname) $cmd]36while {[gets $fd n] > 0} {37foreach spec $pat {38set dst [string range [lindex $spec 0] 0 end-2]39set len [string length $dst]40if {[string equal -length $len $dst $n]} {41set src [string range [lindex $spec 2] 0 end-2]42set spec [list \43$n \44[lindex $spec 1] \45$src[string range $n $len end] \46]47lappend all $spec48}49}50}51close $fd52}5354return [lsort -index 0 -unique $all]55}5657proc load_all_remotes {} {58global repo_config59global all_remotes tracking_branches some_heads_tracking60global remote_url6162set some_heads_tracking 063set all_remotes [list]64set trck [list]6566set rh_str refs/heads/67set rh_len [string length $rh_str]68set rm_dir [gitdir remotes]69if {[file isdirectory $rm_dir]} {70set all_remotes [glob \71-types f \72-tails \73-nocomplain \74-directory $rm_dir *]7576foreach name $all_remotes {77catch {78set fd [open [file join $rm_dir $name] r]79while {[gets $fd line] >= 0} {80if {[regexp {^URL:[ ]*(.+)$} $line line url]} {81set remote_url($name) $url82continue83}84if {![regexp {^Pull:[ ]*([^:]+):(.+)$} \85$line line src dst]} continue86if {[string index $src 0] eq {+}} {87set src [string range $src 1 end]88}89if {![string equal -length 5 refs/ $src]} {90set src $rh_str$src91}92if {![string equal -length 5 refs/ $dst]} {93set dst $rh_str$dst94}95if {[string equal -length $rh_len $rh_str $dst]} {96set some_heads_tracking 197}98lappend trck [list $dst $name $src]99}100close $fd101}102}103}104105foreach line [array names repo_config remote.*.url] {106if {![regexp ^remote\.(.*)\.url\$ $line line name]} continue107lappend all_remotes $name108set remote_url($name) $repo_config(remote.$name.url)109110if {[catch {set fl $repo_config(remote.$name.fetch)}]} {111set fl {}112}113foreach line $fl {114if {![regexp {^([^:]+):(.+)$} $line line src dst]} continue115if {[string index $src 0] eq {+}} {116set src [string range $src 1 end]117}118if {![string equal -length 5 refs/ $src]} {119set src $rh_str$src120}121if {![string equal -length 5 refs/ $dst]} {122set dst $rh_str$dst123}124if {[string equal -length $rh_len $rh_str $dst]} {125set some_heads_tracking 1126}127lappend trck [list $dst $name $src]128}129}130131set tracking_branches [lsort -index 0 -unique $trck]132set all_remotes [lsort -unique $all_remotes]133}134135proc add_fetch_entry {r} {136global repo_config137set remote_m .mbar.remote138set fetch_m $remote_m.fetch139set prune_m $remote_m.prune140set remove_m $remote_m.remove141set enable 0142if {![catch {set a $repo_config(remote.$r.url)}]} {143if {![catch {set a $repo_config(remote.$r.fetch)}]} {144set enable 1145}146} else {147catch {148set fd [open [gitdir remotes $r] r]149while {[gets $fd n] >= 0} {150if {[regexp {^Pull:[ \t]*([^:]+):} $n]} {151set enable 1152break153}154}155close $fd156}157}158159if {$enable} {160if {![winfo exists $fetch_m]} {161menu $remove_m162$remote_m insert 0 cascade \163-label [mc "Remove Remote"] \164-menu $remove_m165166menu $prune_m167$remote_m insert 0 cascade \168-label [mc "Prune from"] \169-menu $prune_m170171menu $fetch_m172$remote_m insert 0 cascade \173-label [mc "Fetch from"] \174-menu $fetch_m175}176177$fetch_m add command \178-label $r \179-command [list fetch_from $r]180$prune_m add command \181-label $r \182-command [list prune_from $r]183$remove_m add command \184-label $r \185-command [list remove_remote $r]186}187}188189proc add_push_entry {r} {190global repo_config191set remote_m .mbar.remote192set push_m $remote_m.push193set enable 0194if {![catch {set a $repo_config(remote.$r.url)}]} {195if {![catch {set a $repo_config(remote.$r.push)}]} {196set enable 1197}198} else {199catch {200set fd [open [gitdir remotes $r] r]201while {[gets $fd n] >= 0} {202if {[regexp {^Push:[ \t]*([^:]+):} $n]} {203set enable 1204break205}206}207close $fd208}209}210211if {$enable} {212if {![winfo exists $push_m]} {213menu $push_m214$remote_m insert 0 cascade \215-label [mc "Push to"] \216-menu $push_m217}218219$push_m add command \220-label $r \221-command [list push_to $r]222}223}224225proc populate_remotes_menu {} {226global all_remotes227228foreach r $all_remotes {229add_fetch_entry $r230add_push_entry $r231}232}233234proc add_single_remote {name location} {235global all_remotes repo_config236lappend all_remotes $name237238git remote add $name $location239240# XXX: Better re-read the config so that we will never get out241# of sync with git remote implementation?242set repo_config(remote.$name.url) $location243set repo_config(remote.$name.fetch) "+refs/heads/*:refs/remotes/$name/*"244245add_fetch_entry $name246add_push_entry $name247}248249proc delete_from_menu {menu name} {250if {[winfo exists $menu]} {251$menu delete $name252}253}254255proc remove_remote {name} {256global all_remotes repo_config257258git remote rm $name259260catch {261# Missing values are ok262unset repo_config(remote.$name.url)263unset repo_config(remote.$name.fetch)264unset repo_config(remote.$name.push)265}266267set i [lsearch -exact all_remotes $name]268lreplace all_remotes $i $i269270set remote_m .mbar.remote271delete_from_menu $remote_m.fetch $name272delete_from_menu $remote_m.prune $name273delete_from_menu $remote_m.remove $name274# Not all remotes are in the push menu275catch { delete_from_menu $remote_m.push $name }276}