summaryrefslogtreecommitdiffstats
path: root/git-gui/lib/tools.tcl
blob: 413f1a170079e0cec78ecdbd1adb7baeb83406f2 (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
160
161
162
163
164
165
166
167
168
# git-gui Tools menu implementation

proc tools_list {} {
	global repo_config

	set names {}
	foreach item [array names repo_config guitool.*.cmd] {
		lappend names [string range $item 8 end-4]
	}
	return [lsort $names]
}

proc tools_populate_all {} {
	global tools_menubar tools_menutbl
	global tools_tailcnt

	set mbar_end [$tools_menubar index end]
	set mbar_base [expr {$mbar_end - $tools_tailcnt}]
	if {$mbar_base >= 0} {
		$tools_menubar delete 0 $mbar_base
	}

	array unset tools_menutbl

	foreach fullname [tools_list] {
		tools_populate_one $fullname
	}
}

proc tools_create_item {parent args} {
	global tools_menubar tools_tailcnt
	if {$parent eq $tools_menubar} {
		set pos [expr {[$parent index end]-$tools_tailcnt+1}]
		eval [list $parent insert $pos] $args
	} else {
		eval [list $parent add] $args
	}
}

proc tools_populate_one {fullname} {
	global tools_menubar tools_menutbl tools_id

	if {![info exists tools_id]} {
		set tools_id 0
	}

	set names [split $fullname '/']
	set parent $tools_menubar
	for {set i 0} {$i < [llength $names]-1} {incr i} {
		set subname [join [lrange $names 0 $i] '/']
		if {[info exists tools_menutbl($subname)]} {
			set parent $tools_menutbl($subname)
		} else {
			set subid $parent.t$tools_id
			tools_create_item $parent cascade \
					-label [lindex $names $i] -menu $subid
			menu $subid
			set tools_menutbl($subname) $subid
			set parent $subid
			incr tools_id
		}
	}

	tools_create_item $parent command \
		-label [lindex $names end] \
		-command [list tools_exec $fullname]
}

proc tools_exec {fullname} {
	global repo_config env current_diff_path
	global current_branch is_detached
	global selected_paths

	if {[is_config_true "guitool.$fullname.needsfile"]} {
		if {$current_diff_path eq {}} {
			error_popup [mc "Running %s requires a selected file." $fullname]
			return
		}
	}

	catch { unset env(ARGS) }
	catch { unset env(REVISION) }

	if {[get_config "guitool.$fullname.revprompt"] ne {} ||
	    [get_config "guitool.$fullname.argprompt"] ne {}} {
		set dlg [tools_askdlg::dialog $fullname]
		if {![tools_askdlg::execute $dlg]} {
			return
		}
	} elseif {[is_config_true "guitool.$fullname.confirm"]} {
		if {[is_config_true "guitool.$fullname.needsfile"]} {
			if {[ask_popup [mc "Are you sure you want to run %1\$s on file \"%2\$s\"?" $fullname $current_diff_path]] ne {yes}} {
				return
			}
		} else {
			if {[ask_popup [mc "Are you sure you want to run %s?" $fullname]] ne {yes}} {
				return
			}
		}
	}

	set env(GIT_GUITOOL) $fullname
	set env(FILENAME) $current_diff_path
	set env(FILENAMES) [join [array names selected_paths] \n]
	if {$is_detached} {
		set env(CUR_BRANCH) ""
	} else {
		set env(CUR_BRANCH) $current_branch
	}

	set cmdline $repo_config(guitool.$fullname.cmd)
	if {[is_config_true "guitool.$fullname.noconsole"]} {
		tools_run_silent [list sh -c $cmdline] \
				 [list tools_complete $fullname {}]
	} else {
		regsub {/} $fullname { / } title
		set w [console::new \
			[mc "Tool: %s" $title] \
			[mc "Running: %s" $cmdline]]
		console::exec $w [list sh -c $cmdline] \
				 [list tools_complete $fullname $w]
	}

	unset env(GIT_GUITOOL)
	unset env(FILENAME)
	unset env(FILENAMES)
	unset env(CUR_BRANCH)
	catch { unset env(ARGS) }
	catch { unset env(REVISION) }
}

proc tools_run_silent {cmd after} {
	lappend cmd 2>@1
	set fd [_open_stdout_stderr $cmd]

	fconfigure $fd -blocking 0 -translation binary
	fileevent $fd readable [list tools_consume_input $fd $after]
}

proc tools_consume_input {fd after} {
	read $fd
	if {[eof $fd]} {
		fconfigure $fd -blocking 1
		if {[catch {close $fd}]} {
			uplevel #0 $after 0
		} else {
			uplevel #0 $after 1
		}
	}
}

proc tools_complete {fullname w {ok 1}} {
	if {$w ne {}} {
		console::done $w $ok
	}

	if {$ok} {
		set msg [mc "Tool completed successfully: %s" $fullname]
	} else {
		set msg [mc "Tool failed: %s" $fullname]
	}

	if {[is_config_true "guitool.$fullname.norescan"]} {
		ui_status $msg
	} else {
		rescan [list ui_status $msg]
	}
}