summaryrefslogtreecommitdiff
path: root/git-gui/lib/remote.tcl
blob: 99f353ed7d793ca9accf2c5d246938c8a51fea02 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# git-gui remote management
# Copyright (C) 2006, 2007 Shawn Pearce

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]} {
			return 1
		}
	}
	return 0
}

proc all_tracking_branches {} {
	global tracking_branches

	set all_trackings {}
	set cmd {}
	foreach name [array names tracking_branches] {
		if {[regsub {/\*$} $name {} name]} {
			lappend cmd $name
		} else {
			regsub ^refs/(heads|remotes)/ $name {} name
			lappend all_trackings $name
		}
	}

	if {$cmd ne {}} {
		set fd [open "| git for-each-ref --format=%(refname) $cmd" r]
		while {[gets $fd name] > 0} {
			regsub ^refs/(heads|remotes)/ $name {} name
			lappend all_trackings $name
		}
		close $fd
	}

	return [lsort -unique $all_trackings]
}

proc load_all_remotes {} {
	global repo_config
	global all_remotes tracking_branches

	set all_remotes [list]
	array unset tracking_branches

	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 {^Pull:[ 	]*([^:]+):(.+)$} \
						$line line src dst]} continue
					if {![regexp ^refs/ $dst]} {
						set dst "refs/heads/$dst"
					}
					set tracking_branches($dst) [list $name $src]
				}
				close $fd
			}
		}
	}

	foreach line [array names repo_config remote.*.url] {
		if {![regexp ^remote\.(.*)\.url\$ $line line name]} continue
		lappend all_remotes $name

		if {[catch {set fl $repo_config(remote.$name.fetch)}]} {
			set fl {}
		}
		foreach line $fl {
			if {![regexp {^([^:]+):(.+)$} $line line src dst]} continue
			if {![regexp ^refs/ $dst]} {
				set dst "refs/heads/$dst"
			}
			set tracking_branches($dst) [list $name $src]
		}
	}

	set all_remotes [lsort -unique $all_remotes]
}

proc populate_fetch_menu {} {
	global all_remotes repo_config

	set m .mbar.fetch
	foreach r $all_remotes {
		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} {
			$m add command \
				-label "Fetch from $r..." \
				-command [list fetch_from $r]
		}
	}
}

proc populate_push_menu {} {
	global all_remotes repo_config

	set m .mbar.push
	set fast_count 0
	foreach r $all_remotes {
		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 {!$fast_count} {
				$m add separator
			}
			$m add command \
				-label "Push to $r..." \
				-command [list push_to $r]
			incr fast_count
		}
	}
}