mirror of
https://github.com/git/git.git
synced 2024-11-05 08:47:56 +01:00
2243ffcc6a
Git-gui does not add most of the remotes to the 'push' menu since they are missing the "Push" line in their remotespec. In that case, removing the remote would end up with an error. Signed-off-by: Petr Baudis <pasky@suse.cz> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
276 lines
5.9 KiB
Tcl
276 lines
5.9 KiB
Tcl
# 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 }
|
|
}
|