Merge git://repo.or.cz/git-gui
* git://repo.or.cz/git-gui: (27 commits)
git-gui: Update German translation.
git-gui: Do not munge conflict marker lines in a normal diff
git-gui: Add a simple implementation of SSH_ASKPASS.
git-gui: Add a dialog that shows the OpenSSH public key.
git-gui: Mark-up strings in show_{other,unmerged}_diff() for localization
git-gui: Show a round number of bytes of large untracked text files
git-gui: Fix the blame viewer destroy handler.
git-gui: Add a search command to the blame viewer.
git-gui: Fix the blame window shape.
git-gui: Fix switch statement in lib/merge.tcl
git-gui: Fix fetching from remotes when adding them
git-gui: Fix removing non-pushable remotes
git-gui: Make input boxes in init/clone/open dialogs consistent
git-gui: Avoid using the term URL when specifying repositories
git-gui: gui.autoexplore makes explorer to pop up automatically after picking
git-gui: Add Explore Working Copy to the Repository menu
git-gui: Use git web--browser for web browsing
git-gui: mkdir -p when initializing new remote repository
git-gui: Add support for removing remotes
git-gui: Add support for adding remotes
...
This commit is contained in:
@ -21,9 +21,11 @@ field w_amov ; # text column: annotations + move tracking
|
||||
field w_asim ; # text column: annotations (simple computation)
|
||||
field w_file ; # text column: actual file data
|
||||
field w_cviewer ; # pane showing commit message
|
||||
field finder ; # find mini-dialog frame
|
||||
field status ; # status mega-widget instance
|
||||
field old_height ; # last known height of $w.file_pane
|
||||
|
||||
|
||||
# Tk UI colors
|
||||
#
|
||||
variable active_color #c0edc5
|
||||
@ -59,7 +61,7 @@ field tooltip_timer {} ; # Current timer event for our tooltip
|
||||
field tooltip_commit {} ; # Commit(s) in tooltip
|
||||
|
||||
constructor new {i_commit i_path i_jump} {
|
||||
global cursor_ptr
|
||||
global cursor_ptr M1B M1T have_tk85
|
||||
variable active_color
|
||||
variable group_colors
|
||||
|
||||
@ -69,6 +71,8 @@ constructor new {i_commit i_path i_jump} {
|
||||
make_toplevel top w
|
||||
wm title $top [append "[appname] ([reponame]): " [mc "File Viewer"]]
|
||||
|
||||
set font_w [font measure font_diff "0"]
|
||||
|
||||
frame $w.header -background gold
|
||||
label $w.header.commit_l \
|
||||
-text [mc "Commit:"] \
|
||||
@ -114,9 +118,9 @@ constructor new {i_commit i_path i_jump} {
|
||||
pack $w_path -fill x -side right
|
||||
pack $w.header.path_l -side right
|
||||
|
||||
panedwindow $w.file_pane -orient vertical
|
||||
frame $w.file_pane.out
|
||||
frame $w.file_pane.cm
|
||||
panedwindow $w.file_pane -orient vertical -borderwidth 0 -sashwidth 3
|
||||
frame $w.file_pane.out -relief flat -borderwidth 1
|
||||
frame $w.file_pane.cm -relief sunken -borderwidth 1
|
||||
$w.file_pane add $w.file_pane.out \
|
||||
-sticky nsew \
|
||||
-minsize 100 \
|
||||
@ -197,6 +201,11 @@ constructor new {i_commit i_path i_jump} {
|
||||
-width 80 \
|
||||
-xscrollcommand [list $w.file_pane.out.sbx set] \
|
||||
-font font_diff
|
||||
if {$have_tk85} {
|
||||
$w_file configure -inactiveselectbackground darkblue
|
||||
}
|
||||
$w_file tag conf found \
|
||||
-background yellow
|
||||
|
||||
set w_columns [list $w_amov $w_asim $w_line $w_file]
|
||||
|
||||
@ -217,6 +226,11 @@ constructor new {i_commit i_path i_jump} {
|
||||
-weight 1
|
||||
grid rowconfigure $w.file_pane.out 0 -weight 1
|
||||
|
||||
set finder [::searchbar::new \
|
||||
$w.file_pane.out.ff $w_file \
|
||||
-column [expr {[llength $w_columns] - 1}] \
|
||||
]
|
||||
|
||||
set w_cviewer $w.file_pane.cm.t
|
||||
text $w_cviewer \
|
||||
-background white \
|
||||
@ -257,6 +271,10 @@ constructor new {i_commit i_path i_jump} {
|
||||
-label [mc "Copy Commit"] \
|
||||
-command [cb _copycommit]
|
||||
$w.ctxm add separator
|
||||
$w.ctxm add command \
|
||||
-label [mc "Find Text..."] \
|
||||
-accelerator F7 \
|
||||
-command [list searchbar::show $finder]
|
||||
menu $w.ctxm.enc
|
||||
build_encoding_menu $w.ctxm.enc [cb _setencoding]
|
||||
$w.ctxm add cascade \
|
||||
@ -278,9 +296,15 @@ constructor new {i_commit i_path i_jump} {
|
||||
$i tag conf color$g -background [lindex $group_colors $g]
|
||||
}
|
||||
|
||||
if {$i eq $w_file} {
|
||||
$w_file tag raise found
|
||||
}
|
||||
$i tag raise sel
|
||||
|
||||
$i conf -cursor $cursor_ptr
|
||||
$i conf -yscrollcommand [list many2scrollbar \
|
||||
$w_columns yview $w.file_pane.out.sby]
|
||||
$i conf -yscrollcommand \
|
||||
"[list ::searchbar::scrolled $finder]
|
||||
[list many2scrollbar $w_columns yview $w.file_pane.out.sby]"
|
||||
bind $i <Button-1> "
|
||||
[cb _hide_tooltip]
|
||||
[cb _click $i @%x,%y]
|
||||
@ -317,6 +341,11 @@ constructor new {i_commit i_path i_jump} {
|
||||
bind $w_cviewer <Tab> "[list focus $w_file];break"
|
||||
bind $w_cviewer <Button-1> [list focus $w_cviewer]
|
||||
bind $w_file <Visibility> [list focus $w_file]
|
||||
bind $top <F7> [list searchbar::show $finder]
|
||||
bind $top <Escape> [list searchbar::hide $finder]
|
||||
bind $top <F3> [list searchbar::find_next $finder]
|
||||
bind $top <Shift-F3> [list searchbar::find_prev $finder]
|
||||
catch { bind $top <Shift-Key-XF86_Switch_VT_3> [list searchbar::find_prev $finder] }
|
||||
|
||||
grid configure $w.header -sticky ew
|
||||
grid configure $w.file_pane -sticky nsew
|
||||
@ -328,9 +357,14 @@ constructor new {i_commit i_path i_jump} {
|
||||
|
||||
set req_w [winfo reqwidth $top]
|
||||
set req_h [winfo reqheight $top]
|
||||
set scr_h [expr {[winfo screenheight $top] - 100}]
|
||||
if {$req_w < 600} {set req_w 600}
|
||||
set scr_w [expr {[winfo screenwidth $top] - 40}]
|
||||
set scr_h [expr {[winfo screenheight $top] - 120}]
|
||||
set opt_w [expr {$font_w * (80 + 5*3 + 3)}]
|
||||
if {$req_w < $opt_w} {set req_w $opt_w}
|
||||
if {$req_w > $scr_w} {set req_w $scr_w}
|
||||
set opt_h [expr {$req_w*4/3}]
|
||||
if {$req_h < $scr_h} {set req_h $scr_h}
|
||||
if {$req_h > $opt_h} {set req_h $opt_h}
|
||||
set g "${req_w}x${req_h}"
|
||||
wm geometry $top $g
|
||||
update
|
||||
@ -338,16 +372,23 @@ constructor new {i_commit i_path i_jump} {
|
||||
set old_height [winfo height $w.file_pane]
|
||||
$w.file_pane sash place 0 \
|
||||
[lindex [$w.file_pane sash coord 0] 0] \
|
||||
[expr {int($old_height * 0.70)}]
|
||||
[expr {int($old_height * 0.80)}]
|
||||
bind $w.file_pane <Configure> \
|
||||
"if {{$w.file_pane} eq {%W}} {[cb _resize %h]}"
|
||||
|
||||
wm protocol $top WM_DELETE_WINDOW "destroy $top"
|
||||
bind $top <Destroy> [cb _kill]
|
||||
bind $top <Destroy> [cb _handle_destroy %W]
|
||||
|
||||
_load $this $i_jump
|
||||
}
|
||||
|
||||
method _handle_destroy {win} {
|
||||
if {$win eq $w} {
|
||||
_kill $this
|
||||
delete_this
|
||||
}
|
||||
}
|
||||
|
||||
method _kill {} {
|
||||
if {$current_fd ne {}} {
|
||||
kill_file_process $current_fd
|
||||
@ -866,6 +907,10 @@ method _showcommit {cur_w lno} {
|
||||
foreach i $w_columns {
|
||||
$i tag conf g$cmit -background $active_color
|
||||
$i tag raise g$cmit
|
||||
if {$i eq $w_file} {
|
||||
$w_file tag raise found
|
||||
}
|
||||
$i tag raise sel
|
||||
}
|
||||
|
||||
set author_name {}
|
||||
|
||||
@ -381,7 +381,8 @@ method _do_new {} {
|
||||
label $w_body.where.l -text [mc "Directory:"]
|
||||
entry $w_body.where.t \
|
||||
-textvariable @local_path \
|
||||
-font font_diff \
|
||||
-borderwidth 1 \
|
||||
-relief sunken \
|
||||
-width 50
|
||||
button $w_body.where.b \
|
||||
-text [mc "Browse"] \
|
||||
@ -463,20 +464,22 @@ method _do_clone {} {
|
||||
frame $w_body.args
|
||||
pack $args -fill both
|
||||
|
||||
label $args.origin_l -text [mc "URL:"]
|
||||
label $args.origin_l -text [mc "Source Location:"]
|
||||
entry $args.origin_t \
|
||||
-textvariable @origin_url \
|
||||
-font font_diff \
|
||||
-borderwidth 1 \
|
||||
-relief sunken \
|
||||
-width 50
|
||||
button $args.origin_b \
|
||||
-text [mc "Browse"] \
|
||||
-command [cb _open_origin]
|
||||
grid $args.origin_l $args.origin_t $args.origin_b -sticky ew
|
||||
|
||||
label $args.where_l -text [mc "Directory:"]
|
||||
label $args.where_l -text [mc "Target Directory:"]
|
||||
entry $args.where_t \
|
||||
-textvariable @local_path \
|
||||
-font font_diff \
|
||||
-borderwidth 1 \
|
||||
-relief sunken \
|
||||
-width 50
|
||||
button $args.where_b \
|
||||
-text [mc "Browse"] \
|
||||
@ -979,7 +982,8 @@ method _do_open {} {
|
||||
label $w_body.where.l -text [mc "Repository:"]
|
||||
entry $w_body.where.t \
|
||||
-textvariable @local_path \
|
||||
-font font_diff \
|
||||
-borderwidth 1 \
|
||||
-relief sunken \
|
||||
-width 50
|
||||
button $w_body.where.b \
|
||||
-text [mc "Browse"] \
|
||||
|
||||
@ -117,22 +117,22 @@ proc show_unmerged_diff {cont_info} {
|
||||
if {$merge_stages(2) eq {}} {
|
||||
set is_conflict_diff 1
|
||||
lappend current_diff_queue \
|
||||
[list "LOCAL: deleted\nREMOTE:\n" d======= \
|
||||
[list [mc "LOCAL: deleted\nREMOTE:\n"] d======= \
|
||||
[list ":1:$current_diff_path" ":3:$current_diff_path"]]
|
||||
} elseif {$merge_stages(3) eq {}} {
|
||||
set is_conflict_diff 1
|
||||
lappend current_diff_queue \
|
||||
[list "REMOTE: deleted\nLOCAL:\n" d======= \
|
||||
[list [mc "REMOTE: deleted\nLOCAL:\n"] d======= \
|
||||
[list ":1:$current_diff_path" ":2:$current_diff_path"]]
|
||||
} elseif {[lindex $merge_stages(1) 0] eq {120000}
|
||||
|| [lindex $merge_stages(2) 0] eq {120000}
|
||||
|| [lindex $merge_stages(3) 0] eq {120000}} {
|
||||
set is_conflict_diff 1
|
||||
lappend current_diff_queue \
|
||||
[list "LOCAL:\n" d======= \
|
||||
[list [mc "LOCAL:\n"] d======= \
|
||||
[list ":1:$current_diff_path" ":2:$current_diff_path"]]
|
||||
lappend current_diff_queue \
|
||||
[list "REMOTE:\n" d======= \
|
||||
[list [mc "REMOTE:\n"] d======= \
|
||||
[list ":1:$current_diff_path" ":3:$current_diff_path"]]
|
||||
} else {
|
||||
start_show_diff $cont_info
|
||||
@ -164,7 +164,7 @@ proc show_other_diff {path w m cont_info} {
|
||||
# - Git won't give us the diff, there's nothing to compare to!
|
||||
#
|
||||
if {$m eq {_O}} {
|
||||
set max_sz [expr {128 * 1024}]
|
||||
set max_sz 100000
|
||||
set type unknown
|
||||
if {[catch {
|
||||
set type [file type $path]
|
||||
@ -218,17 +218,17 @@ proc show_other_diff {path w m cont_info} {
|
||||
d_@
|
||||
} else {
|
||||
if {$sz > $max_sz} {
|
||||
$ui_diff insert end \
|
||||
"* Untracked file is $sz bytes.
|
||||
* Showing only first $max_sz bytes.
|
||||
" d_@
|
||||
$ui_diff insert end [mc \
|
||||
"* Untracked file is %d bytes.
|
||||
* Showing only first %d bytes.
|
||||
" $sz $max_sz] d_@
|
||||
}
|
||||
$ui_diff insert end $content
|
||||
if {$sz > $max_sz} {
|
||||
$ui_diff insert end "
|
||||
* Untracked file clipped here by [appname].
|
||||
$ui_diff insert end [mc "
|
||||
* Untracked file clipped here by %s.
|
||||
* To see the entire file, use an external editor.
|
||||
" d_@
|
||||
" [appname]] d_@
|
||||
}
|
||||
}
|
||||
$ui_diff conf -state disabled
|
||||
@ -377,7 +377,6 @@ proc read_diff {fd cont_info} {
|
||||
{+} {
|
||||
if {[regexp {^\+([<>]{7} |={7})} $line _g op]} {
|
||||
set is_conflict_diff 1
|
||||
set line [string replace $line 0 0 { }]
|
||||
set tags d$op
|
||||
} else {
|
||||
set tags d_+
|
||||
|
||||
@ -298,11 +298,18 @@ proc add_helper {txt paths} {
|
||||
set after {}
|
||||
foreach path $paths {
|
||||
switch -glob -- [lindex $file_states($path) 0] {
|
||||
_U -
|
||||
U? {
|
||||
if {$path eq $current_diff_path} {
|
||||
unlock_index
|
||||
merge_stage_workdir $path
|
||||
return
|
||||
}
|
||||
}
|
||||
_O -
|
||||
?M -
|
||||
?D -
|
||||
?T -
|
||||
U? {
|
||||
?T {
|
||||
lappend pathList $path
|
||||
if {$path eq $current_diff_path} {
|
||||
set after {reshow_diff;}
|
||||
|
||||
@ -40,6 +40,7 @@ The rescan will be automatically started now.
|
||||
_O {
|
||||
continue; # and pray it works!
|
||||
}
|
||||
_U -
|
||||
U? {
|
||||
error_popup [mc "You are in the middle of a conflicted merge.
|
||||
|
||||
|
||||
@ -23,13 +23,14 @@ This operation can be undone only by restarting the merge." \
|
||||
}
|
||||
}
|
||||
|
||||
proc merge_stage_workdir {path w lno} {
|
||||
proc merge_stage_workdir {path {lno {}}} {
|
||||
global current_diff_path diff_active
|
||||
global current_diff_side ui_workdir
|
||||
|
||||
if {$diff_active} return
|
||||
|
||||
if {$path ne $current_diff_path} {
|
||||
show_diff $path $w $lno {} [list do_merge_stage_workdir $path]
|
||||
if {$path ne $current_diff_path || $ui_workdir ne $current_diff_side} {
|
||||
show_diff $path $ui_workdir $lno {} [list do_merge_stage_workdir $path]
|
||||
} else {
|
||||
do_merge_stage_workdir $path
|
||||
}
|
||||
@ -375,14 +376,6 @@ proc merge_tool_finish {fd} {
|
||||
}
|
||||
}
|
||||
|
||||
# Check the modification time of the target file
|
||||
if {!$failed && [file mtime $mtool_target] eq $mtool_mtime} {
|
||||
if {[ask_popup [mc "File %s unchanged, still accept as resolved?" \
|
||||
[short_path $mtool_target]]] ne {yes}} {
|
||||
set failed 1
|
||||
}
|
||||
}
|
||||
|
||||
# Finish
|
||||
if {$failed} {
|
||||
file rename -force -- $backup $mtool_target
|
||||
@ -395,6 +388,6 @@ proc merge_tool_finish {fd} {
|
||||
|
||||
delete_temp_files $mtool_tmpfiles
|
||||
|
||||
merge_add_resolution $mtool_target
|
||||
reshow_diff
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,91 +132,145 @@ proc load_all_remotes {} {
|
||||
set all_remotes [lsort -unique $all_remotes]
|
||||
}
|
||||
|
||||
proc populate_fetch_menu {} {
|
||||
global all_remotes repo_config
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
if {$enable} {
|
||||
if {![winfo exists $fetch_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]
|
||||
}
|
||||
$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 populate_push_menu {} {
|
||||
global all_remotes repo_config
|
||||
|
||||
proc add_push_entry {r} {
|
||||
global repo_config
|
||||
set remote_m .mbar.remote
|
||||
set push_m $remote_m.push
|
||||
|
||||
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
|
||||
}
|
||||
set enable 0
|
||||
if {![catch {set a $repo_config(remote.$r.url)}]} {
|
||||
if {![catch {set a $repo_config(remote.$r.push)}]} {
|
||||
set enable 1
|
||||
}
|
||||
|
||||
if {$enable} {
|
||||
if {![winfo exists $push_m]} {
|
||||
menu $push_m
|
||||
$remote_m insert 0 cascade \
|
||||
-label [mc "Push to"] \
|
||||
-menu $push_m
|
||||
} else {
|
||||
catch {
|
||||
set fd [open [gitdir remotes $r] r]
|
||||
while {[gets $fd n] >= 0} {
|
||||
if {[regexp {^Push:[ \t]*([^:]+):} $n]} {
|
||||
set enable 1
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
$push_m add command \
|
||||
-label $r \
|
||||
-command [list push_to $r]
|
||||
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 }
|
||||
}
|
||||
|
||||
191
git-gui/lib/remote_add.tcl
Normal file
191
git-gui/lib/remote_add.tcl
Normal file
@ -0,0 +1,191 @@
|
||||
# git-gui remote adding support
|
||||
# Copyright (C) 2008 Petr Baudis
|
||||
|
||||
class remote_add {
|
||||
|
||||
field w ; # widget path
|
||||
field w_name ; # new remote name widget
|
||||
field w_loc ; # new remote location widget
|
||||
|
||||
field name {}; # name of the remote the user has chosen
|
||||
field location {}; # location of the remote the user has chosen
|
||||
|
||||
field opt_action fetch; # action to do after registering the remote locally
|
||||
|
||||
constructor dialog {} {
|
||||
global repo_config
|
||||
|
||||
make_toplevel top w
|
||||
wm title $top [append "[appname] ([reponame]): " [mc "Add Remote"]]
|
||||
if {$top ne {.}} {
|
||||
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
|
||||
}
|
||||
|
||||
label $w.header -text [mc "Add New Remote"] -font font_uibold
|
||||
pack $w.header -side top -fill x
|
||||
|
||||
frame $w.buttons
|
||||
button $w.buttons.create -text [mc Add] \
|
||||
-default active \
|
||||
-command [cb _add]
|
||||
pack $w.buttons.create -side right
|
||||
button $w.buttons.cancel -text [mc Cancel] \
|
||||
-command [list destroy $w]
|
||||
pack $w.buttons.cancel -side right -padx 5
|
||||
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
|
||||
|
||||
labelframe $w.desc -text [mc "Remote Details"]
|
||||
|
||||
label $w.desc.name_l -text [mc "Name:"]
|
||||
set w_name $w.desc.name_t
|
||||
entry $w_name \
|
||||
-borderwidth 1 \
|
||||
-relief sunken \
|
||||
-width 40 \
|
||||
-textvariable @name \
|
||||
-validate key \
|
||||
-validatecommand [cb _validate_name %d %S]
|
||||
grid $w.desc.name_l $w_name -sticky we -padx {0 5}
|
||||
|
||||
label $w.desc.loc_l -text [mc "Location:"]
|
||||
set w_loc $w.desc.loc_t
|
||||
entry $w_loc \
|
||||
-borderwidth 1 \
|
||||
-relief sunken \
|
||||
-width 40 \
|
||||
-textvariable @location
|
||||
grid $w.desc.loc_l $w_loc -sticky we -padx {0 5}
|
||||
|
||||
grid columnconfigure $w.desc 1 -weight 1
|
||||
pack $w.desc -anchor nw -fill x -pady 5 -padx 5
|
||||
|
||||
labelframe $w.action -text [mc "Further Action"]
|
||||
|
||||
radiobutton $w.action.fetch \
|
||||
-text [mc "Fetch Immediately"] \
|
||||
-value fetch \
|
||||
-variable @opt_action
|
||||
pack $w.action.fetch -anchor nw
|
||||
|
||||
radiobutton $w.action.push \
|
||||
-text [mc "Initialize Remote Repository and Push"] \
|
||||
-value push \
|
||||
-variable @opt_action
|
||||
pack $w.action.push -anchor nw
|
||||
|
||||
radiobutton $w.action.none \
|
||||
-text [mc "Do Nothing Else Now"] \
|
||||
-value none \
|
||||
-variable @opt_action
|
||||
pack $w.action.none -anchor nw
|
||||
|
||||
grid columnconfigure $w.action 1 -weight 1
|
||||
pack $w.action -anchor nw -fill x -pady 5 -padx 5
|
||||
|
||||
bind $w <Visibility> [cb _visible]
|
||||
bind $w <Key-Escape> [list destroy $w]
|
||||
bind $w <Key-Return> [cb _add]\;break
|
||||
tkwait window $w
|
||||
}
|
||||
|
||||
method _add {} {
|
||||
global repo_config env
|
||||
global M1B
|
||||
|
||||
if {$name eq {}} {
|
||||
tk_messageBox \
|
||||
-icon error \
|
||||
-type ok \
|
||||
-title [wm title $w] \
|
||||
-parent $w \
|
||||
-message [mc "Please supply a remote name."]
|
||||
focus $w_name
|
||||
return
|
||||
}
|
||||
|
||||
# XXX: We abuse check-ref-format here, but
|
||||
# that should be ok.
|
||||
if {[catch {git check-ref-format "remotes/$name"}]} {
|
||||
tk_messageBox \
|
||||
-icon error \
|
||||
-type ok \
|
||||
-title [wm title $w] \
|
||||
-parent $w \
|
||||
-message [mc "'%s' is not an acceptable remote name." $name]
|
||||
focus $w_name
|
||||
return
|
||||
}
|
||||
|
||||
if {[catch {add_single_remote $name $location}]} {
|
||||
tk_messageBox \
|
||||
-icon error \
|
||||
-type ok \
|
||||
-title [wm title $w] \
|
||||
-parent $w \
|
||||
-message [mc "Failed to add remote '%s' of location '%s'." $name $location]
|
||||
focus $w_name
|
||||
return
|
||||
}
|
||||
|
||||
switch -- $opt_action {
|
||||
fetch {
|
||||
set c [console::new \
|
||||
[mc "fetch %s" $name] \
|
||||
[mc "Fetching the %s" $name]]
|
||||
console::exec $c [list git fetch $name]
|
||||
}
|
||||
push {
|
||||
set cmds [list]
|
||||
|
||||
# Parse the location
|
||||
if { [regexp {(?:git\+)?ssh://([^/]+)(/.+)} $location xx host path]
|
||||
|| [regexp {([^:][^:]+):(.+)} $location xx host path]} {
|
||||
set ssh ssh
|
||||
if {[info exists env(GIT_SSH)]} {
|
||||
set ssh $env(GIT_SSH)
|
||||
}
|
||||
lappend cmds [list exec $ssh $host mkdir -p $location && git --git-dir=$path init --bare]
|
||||
} elseif { ! [regexp {://} $location xx] } {
|
||||
lappend cmds [list exec mkdir -p $location]
|
||||
lappend cmds [list exec git --git-dir=$location init --bare]
|
||||
} else {
|
||||
tk_messageBox \
|
||||
-icon error \
|
||||
-type ok \
|
||||
-title [wm title $w] \
|
||||
-parent $w \
|
||||
-message [mc "Do not know how to initialize repository at location '%s'." $location]
|
||||
destroy $w
|
||||
return
|
||||
}
|
||||
|
||||
set c [console::new \
|
||||
[mc "push %s" $name] \
|
||||
[mc "Setting up the %s (at %s)" $name $location]]
|
||||
|
||||
lappend cmds [list exec git push -v --all $name]
|
||||
console::chain $c $cmds
|
||||
}
|
||||
none {
|
||||
}
|
||||
}
|
||||
|
||||
destroy $w
|
||||
}
|
||||
|
||||
method _validate_name {d S} {
|
||||
if {$d == 1} {
|
||||
if {[regexp {[~^:?*\[\0- ]} $S]} {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
method _visible {} {
|
||||
grab $w
|
||||
$w_name icursor end
|
||||
focus $w_name
|
||||
}
|
||||
|
||||
}
|
||||
@ -26,12 +26,12 @@ constructor dialog {} {
|
||||
global all_remotes M1B
|
||||
|
||||
make_toplevel top w
|
||||
wm title $top [append "[appname] ([reponame]): " [mc "Delete Remote Branch"]]
|
||||
wm title $top [append "[appname] ([reponame]): " [mc "Delete Branch Remotely"]]
|
||||
if {$top ne {.}} {
|
||||
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
|
||||
}
|
||||
|
||||
label $w.header -text [mc "Delete Remote Branch"] -font font_uibold
|
||||
label $w.header -text [mc "Delete Branch Remotely"] -font font_uibold
|
||||
pack $w.header -side top -fill x
|
||||
|
||||
frame $w.buttons
|
||||
@ -63,7 +63,7 @@ constructor dialog {} {
|
||||
set urltype url
|
||||
}
|
||||
radiobutton $w.dest.url_r \
|
||||
-text [mc "Arbitrary URL:"] \
|
||||
-text [mc "Arbitrary Location:"] \
|
||||
-value url \
|
||||
-variable @urltype
|
||||
entry $w.dest.url_t \
|
||||
|
||||
190
git-gui/lib/search.tcl
Normal file
190
git-gui/lib/search.tcl
Normal file
@ -0,0 +1,190 @@
|
||||
# incremental search panel
|
||||
# based on code from gitk, Copyright (C) Paul Mackerras
|
||||
|
||||
class searchbar {
|
||||
|
||||
field w
|
||||
field ctext
|
||||
|
||||
field searchstring {}
|
||||
field casesensitive 1
|
||||
field searchdirn -forwards
|
||||
|
||||
field smarktop
|
||||
field smarkbot
|
||||
|
||||
constructor new {i_w i_text args} {
|
||||
set w $i_w
|
||||
set ctext $i_text
|
||||
|
||||
frame $w
|
||||
label $w.l -text [mc Find:]
|
||||
button $w.bn -text [mc Next] -command [cb find_next]
|
||||
button $w.bp -text [mc Prev] -command [cb find_prev]
|
||||
checkbutton $w.cs -text [mc Case-Sensitive] \
|
||||
-variable ${__this}::casesensitive -command [cb _incrsearch]
|
||||
entry $w.ent -textvariable ${__this}::searchstring -background lightgreen
|
||||
pack $w.l -side left
|
||||
pack $w.cs -side right
|
||||
pack $w.bp -side right
|
||||
pack $w.bn -side right
|
||||
pack $w.ent -side left -expand 1 -fill x
|
||||
|
||||
eval grid conf $w -sticky we $args
|
||||
grid remove $w
|
||||
|
||||
trace add variable searchstring write [cb _incrsearch_cb]
|
||||
|
||||
bind $w <Destroy> [cb delete_this]
|
||||
return $this
|
||||
}
|
||||
|
||||
method show {} {
|
||||
if {![winfo ismapped $w]} {
|
||||
grid $w
|
||||
}
|
||||
focus -force $w.ent
|
||||
}
|
||||
|
||||
method hide {} {
|
||||
if {[winfo ismapped $w]} {
|
||||
focus $ctext
|
||||
grid remove $w
|
||||
}
|
||||
}
|
||||
|
||||
method _get_new_anchor {} {
|
||||
# use start of selection if it is visible,
|
||||
# or the bounds of the visible area
|
||||
set top [$ctext index @0,0]
|
||||
set bottom [$ctext index @0,[winfo height $ctext]]
|
||||
set sel [$ctext tag ranges sel]
|
||||
if {$sel ne {}} {
|
||||
set spos [lindex $sel 0]
|
||||
if {[lindex $spos 0] >= [lindex $top 0] &&
|
||||
[lindex $spos 0] <= [lindex $bottom 0]} {
|
||||
return $spos
|
||||
}
|
||||
}
|
||||
if {$searchdirn eq "-forwards"} {
|
||||
return $top
|
||||
} else {
|
||||
return $bottom
|
||||
}
|
||||
}
|
||||
|
||||
method _get_wrap_anchor {dir} {
|
||||
if {$dir eq "-forwards"} {
|
||||
return 1.0
|
||||
} else {
|
||||
return end
|
||||
}
|
||||
}
|
||||
|
||||
method _do_search {start {mlenvar {}} {dir {}} {endbound {}}} {
|
||||
set cmd [list $ctext search]
|
||||
if {$mlenvar ne {}} {
|
||||
upvar $mlenvar mlen
|
||||
lappend cmd -count mlen
|
||||
}
|
||||
if {!$casesensitive} {
|
||||
lappend cmd -nocase
|
||||
}
|
||||
if {$dir eq {}} {
|
||||
set dir $searchdirn
|
||||
}
|
||||
lappend cmd $dir -- $searchstring
|
||||
if {$endbound ne {}} {
|
||||
set here [eval $cmd [list $start] [list $endbound]]
|
||||
} else {
|
||||
set here [eval $cmd [list $start]]
|
||||
if {$here eq {}} {
|
||||
set here [eval $cmd [_get_wrap_anchor $this $dir]]
|
||||
}
|
||||
}
|
||||
return $here
|
||||
}
|
||||
|
||||
method _incrsearch_cb {name ix op} {
|
||||
after idle [cb _incrsearch]
|
||||
}
|
||||
|
||||
method _incrsearch {} {
|
||||
$ctext tag remove found 1.0 end
|
||||
if {[catch {$ctext index anchor}]} {
|
||||
$ctext mark set anchor [_get_new_anchor $this]
|
||||
}
|
||||
if {$searchstring ne {}} {
|
||||
set here [_do_search $this anchor mlen]
|
||||
if {$here ne {}} {
|
||||
$ctext see $here
|
||||
$ctext tag remove sel 1.0 end
|
||||
$ctext tag add sel $here "$here + $mlen c"
|
||||
$w.ent configure -background lightgreen
|
||||
_set_marks $this 1
|
||||
} else {
|
||||
$w.ent configure -background lightpink
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
method find_prev {} {
|
||||
find_next $this -backwards
|
||||
}
|
||||
|
||||
method find_next {{dir -forwards}} {
|
||||
focus $w.ent
|
||||
$w.ent icursor end
|
||||
set searchdirn $dir
|
||||
$ctext mark unset anchor
|
||||
if {$searchstring ne {}} {
|
||||
set start [_get_new_anchor $this]
|
||||
if {$dir eq "-forwards"} {
|
||||
set start "$start + 1c"
|
||||
}
|
||||
set match [_do_search $this $start mlen]
|
||||
$ctext tag remove sel 1.0 end
|
||||
if {$match ne {}} {
|
||||
$ctext see $match
|
||||
$ctext tag add sel $match "$match + $mlen c"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
method _mark_range {first last} {
|
||||
set mend $first.0
|
||||
while {1} {
|
||||
set match [_do_search $this $mend mlen -forwards $last.end]
|
||||
if {$match eq {}} break
|
||||
set mend "$match + $mlen c"
|
||||
$ctext tag add found $match $mend
|
||||
}
|
||||
}
|
||||
|
||||
method _set_marks {doall} {
|
||||
set topline [lindex [split [$ctext index @0,0] .] 0]
|
||||
set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
|
||||
if {$doall || $botline < $smarktop || $topline > $smarkbot} {
|
||||
# no overlap with previous
|
||||
_mark_range $this $topline $botline
|
||||
set smarktop $topline
|
||||
set smarkbot $botline
|
||||
} else {
|
||||
if {$topline < $smarktop} {
|
||||
_mark_range $this $topline [expr {$smarktop-1}]
|
||||
set smarktop $topline
|
||||
}
|
||||
if {$botline > $smarkbot} {
|
||||
_mark_range $this [expr {$smarkbot+1}] $botline
|
||||
set smarkbot $botline
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
method scrolled {} {
|
||||
if {$searchstring ne {}} {
|
||||
after idle [cb _set_marks 0]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -80,7 +80,7 @@ method _connect {pipe_fd} {
|
||||
error_popup [strcat [mc "Unrecognized spell checker"] ":\n\n$s_version"]
|
||||
return
|
||||
}
|
||||
set s_version [string range $s_version 5 end]
|
||||
set s_version [string range [string trim $s_version] 5 end]
|
||||
regexp \
|
||||
{International Ispell Version .* \(but really (Aspell .*?)\)$} \
|
||||
$s_version _junk s_version
|
||||
@ -314,6 +314,7 @@ method _run {} {
|
||||
method _read {} {
|
||||
while {[gets $s_fd line] >= 0} {
|
||||
set lineno [lindex $s_pending 0 0]
|
||||
set line [string trim $line]
|
||||
|
||||
if {$s_clear} {
|
||||
$w_text tag remove misspelled "$lineno.0" "$lineno.end"
|
||||
|
||||
126
git-gui/lib/sshkey.tcl
Normal file
126
git-gui/lib/sshkey.tcl
Normal file
@ -0,0 +1,126 @@
|
||||
# git-gui about git-gui dialog
|
||||
# Copyright (C) 2006, 2007 Shawn Pearce
|
||||
|
||||
proc find_ssh_key {} {
|
||||
foreach name {~/.ssh/id_dsa.pub ~/.ssh/id_rsa.pub ~/.ssh/identity.pub} {
|
||||
if {[file exists $name]} {
|
||||
set fh [open $name r]
|
||||
set cont [read $fh]
|
||||
close $fh
|
||||
return [list $name $cont]
|
||||
}
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
proc do_ssh_key {} {
|
||||
global sshkey_title have_tk85 sshkey_fd
|
||||
|
||||
set w .sshkey_dialog
|
||||
if {[winfo exists $w]} {
|
||||
raise $w
|
||||
return
|
||||
}
|
||||
|
||||
toplevel $w
|
||||
wm transient $w .
|
||||
|
||||
set finfo [find_ssh_key]
|
||||
if {$finfo eq {}} {
|
||||
set sshkey_title [mc "No keys found."]
|
||||
set gen_state normal
|
||||
} else {
|
||||
set sshkey_title [mc "Found a public key in: %s" [lindex $finfo 0]]
|
||||
set gen_state disabled
|
||||
}
|
||||
|
||||
frame $w.header -relief flat
|
||||
label $w.header.lbl -textvariable sshkey_title -anchor w
|
||||
button $w.header.gen -text [mc "Generate Key"] \
|
||||
-command [list make_ssh_key $w] -state $gen_state
|
||||
pack $w.header.lbl -side left -expand 1 -fill x
|
||||
pack $w.header.gen -side right
|
||||
pack $w.header -fill x -pady 5 -padx 5
|
||||
|
||||
text $w.contents -width 60 -height 10 -wrap char -relief sunken
|
||||
pack $w.contents -fill both -expand 1
|
||||
if {$have_tk85} {
|
||||
$w.contents configure -inactiveselectbackground darkblue
|
||||
}
|
||||
|
||||
frame $w.buttons
|
||||
button $w.buttons.close -text [mc Close] \
|
||||
-default active -command [list destroy $w]
|
||||
pack $w.buttons.close -side right
|
||||
button $w.buttons.copy -text [mc "Copy To Clipboard"] \
|
||||
-command [list tk_textCopy $w.contents]
|
||||
pack $w.buttons.copy -side left
|
||||
pack $w.buttons -side bottom -fill x -pady 5 -padx 5
|
||||
|
||||
if {$finfo ne {}} {
|
||||
$w.contents insert end [lindex $finfo 1] sel
|
||||
}
|
||||
$w.contents configure -state disabled
|
||||
|
||||
bind $w <Visibility> "grab $w; focus $w.buttons.close"
|
||||
bind $w <Key-Escape> "destroy $w"
|
||||
bind $w <Key-Return> "destroy $w"
|
||||
bind $w <Destroy> kill_sshkey
|
||||
wm title $w [mc "Your OpenSSH Public Key"]
|
||||
tk::PlaceWindow $w widget .
|
||||
tkwait window $w
|
||||
}
|
||||
|
||||
proc make_ssh_key {w} {
|
||||
global sshkey_title sshkey_output sshkey_fd
|
||||
|
||||
set sshkey_title [mc "Generating..."]
|
||||
$w.header.gen configure -state disabled
|
||||
|
||||
set cmdline [list sh -c {echo | ssh-keygen -q -t rsa -f ~/.ssh/id_rsa 2>&1}]
|
||||
|
||||
if {[catch { set sshkey_fd [_open_stdout_stderr $cmdline] } err]} {
|
||||
error_popup [mc "Could not start ssh-keygen:\n\n%s" $err]
|
||||
return
|
||||
}
|
||||
|
||||
set sshkey_output {}
|
||||
fconfigure $sshkey_fd -blocking 0
|
||||
fileevent $sshkey_fd readable [list read_sshkey_output $sshkey_fd $w]
|
||||
}
|
||||
|
||||
proc kill_sshkey {} {
|
||||
global sshkey_fd
|
||||
if {![info exists sshkey_fd]} return
|
||||
catch { kill_file_process $sshkey_fd }
|
||||
catch { close $sshkey_fd }
|
||||
}
|
||||
|
||||
proc read_sshkey_output {fd w} {
|
||||
global sshkey_fd sshkey_output sshkey_title
|
||||
|
||||
set sshkey_output "$sshkey_output[read $fd]"
|
||||
if {![eof $fd]} return
|
||||
|
||||
fconfigure $fd -blocking 1
|
||||
unset sshkey_fd
|
||||
|
||||
$w.contents configure -state normal
|
||||
if {[catch {close $fd} err]} {
|
||||
set sshkey_title [mc "Generation failed."]
|
||||
$w.contents insert end $err
|
||||
$w.contents insert end "\n"
|
||||
$w.contents insert end $sshkey_output
|
||||
} else {
|
||||
set finfo [find_ssh_key]
|
||||
if {$finfo eq {}} {
|
||||
set sshkey_title [mc "Generation succeded, but no keys found."]
|
||||
$w.contents insert end $sshkey_output
|
||||
} else {
|
||||
set sshkey_title [mc "Your key is in: %s" [lindex $finfo 0]]
|
||||
$w.contents insert end [lindex $finfo 1] sel
|
||||
}
|
||||
}
|
||||
$w.contents configure -state disable
|
||||
}
|
||||
@ -135,7 +135,7 @@ proc do_push_anywhere {} {
|
||||
set push_urltype url
|
||||
}
|
||||
radiobutton $w.dest.url_r \
|
||||
-text [mc "Arbitrary URL:"] \
|
||||
-text [mc "Arbitrary Location:"] \
|
||||
-value url \
|
||||
-variable push_urltype
|
||||
entry $w.dest.url_t \
|
||||
|
||||
Reference in New Issue
Block a user