revert(3p/git): Revert merge of git upstream at v2.26.2
This causes cgit to serve error pages, which is undesirable. This reverts commit5229c9b232, reversing changes made tof2b211131f.
This commit is contained in:
		
							parent
							
								
									6f8fbf4aa4
								
							
						
					
					
						commit
						93ba78d6f4
					
				
					 1006 changed files with 60537 additions and 148724 deletions
				
			
		
							
								
								
									
										24
									
								
								third_party/git/git-gui/lib/blame.tcl
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								third_party/git/git-gui/lib/blame.tcl
									
										
									
									
										vendored
									
									
								
							|  | @ -24,7 +24,6 @@ field w_cviewer  ; # pane showing commit message | |||
| field finder     ; # find mini-dialog frame | ||||
| field gotoline   ; # line goto mini-dialog frame | ||||
| field status     ; # status mega-widget instance | ||||
| field status_operation ; # operation displayed by status mega-widget | ||||
| field old_height ; # last known height of $w.file_pane | ||||
| 
 | ||||
| 
 | ||||
|  | @ -275,7 +274,6 @@ constructor new {i_commit i_path i_jump} { | |||
| 	pack $w_cviewer -expand 1 -fill both | ||||
| 
 | ||||
| 	set status [::status_bar::new $w.status] | ||||
| 	set status_operation {} | ||||
| 
 | ||||
| 	menu $w.ctxm -tearoff 0 | ||||
| 	$w.ctxm add command \ | ||||
|  | @ -604,23 +602,16 @@ method _exec_blame {cur_w cur_d options cur_s} { | |||
| 	} else { | ||||
| 		lappend options $commit | ||||
| 	} | ||||
| 
 | ||||
| 	# We may recurse in from another call to _exec_blame and already have | ||||
| 	# a status operation. | ||||
| 	if {$status_operation == {}} { | ||||
| 		set status_operation [$status start \ | ||||
| 			$cur_s \ | ||||
| 			[mc "lines annotated"]] | ||||
| 	} else { | ||||
| 		$status_operation restart $cur_s | ||||
| 	} | ||||
| 
 | ||||
| 	lappend options -- $path | ||||
| 	set fd [eval git_read --nice blame $options] | ||||
| 	fconfigure $fd -blocking 0 -translation lf -encoding utf-8 | ||||
| 	fileevent $fd readable [cb _read_blame $fd $cur_w $cur_d] | ||||
| 	set current_fd $fd | ||||
| 	set blame_lines 0 | ||||
| 
 | ||||
| 	$status start \ | ||||
| 		$cur_s \ | ||||
| 		[mc "lines annotated"] | ||||
| } | ||||
| 
 | ||||
| method _read_blame {fd cur_w cur_d} { | ||||
|  | @ -815,11 +806,10 @@ method _read_blame {fd cur_w cur_d} { | |||
| 				[mc "Loading original location annotations..."] | ||||
| 		} else { | ||||
| 			set current_fd {} | ||||
| 			$status_operation stop [mc "Annotation complete."] | ||||
| 			set status_operation {} | ||||
| 			$status stop [mc "Annotation complete."] | ||||
| 		} | ||||
| 	} else { | ||||
| 		$status_operation update $blame_lines $total_lines | ||||
| 		$status update $blame_lines $total_lines | ||||
| 	} | ||||
| } ifdeleted { catch {close $fd} } | ||||
| 
 | ||||
|  | @ -1134,7 +1124,7 @@ method _blameparent {} { | |||
| 			set diffcmd [list diff-tree --unified=0 $cparent $cmit -- $new_path] | ||||
| 		} | ||||
| 		if {[catch {set fd [eval git_read $diffcmd]} err]} { | ||||
| 			$status_operation stop [mc "Unable to display parent"] | ||||
| 			$status stop [mc "Unable to display parent"] | ||||
| 			error_popup [strcat [mc "Error loading diff:"] "\n\n$err"] | ||||
| 			return | ||||
| 		} | ||||
|  |  | |||
							
								
								
									
										2
									
								
								third_party/git/git-gui/lib/branch.tcl
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								third_party/git/git-gui/lib/branch.tcl
									
										
									
									
										vendored
									
									
								
							|  | @ -8,7 +8,6 @@ proc load_all_heads {} { | |||
| 	set rh_len [expr {[string length $rh] + 1}] | ||||
| 	set all_heads [list] | ||||
| 	set fd [git_read for-each-ref --format=%(refname) $rh] | ||||
| 	fconfigure $fd -translation binary -encoding utf-8 | ||||
| 	while {[gets $fd line] > 0} { | ||||
| 		if {!$some_heads_tracking || ![is_tracking_branch $line]} { | ||||
| 			lappend all_heads [string range $line $rh_len end] | ||||
|  | @ -25,7 +24,6 @@ proc load_all_tags {} { | |||
| 		--sort=-taggerdate \ | ||||
| 		--format=%(refname) \ | ||||
| 		refs/tags] | ||||
| 	fconfigure $fd -translation binary -encoding utf-8 | ||||
| 	while {[gets $fd line] > 0} { | ||||
| 		if {![regsub ^refs/tags/ $line {} name]} continue | ||||
| 		lappend all_tags $name | ||||
|  |  | |||
							
								
								
									
										21
									
								
								third_party/git/git-gui/lib/checkout_op.tcl
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								third_party/git/git-gui/lib/checkout_op.tcl
									
										
									
									
										vendored
									
									
								
							|  | @ -341,9 +341,9 @@ method _readtree {} { | |||
| 	global HEAD | ||||
| 
 | ||||
| 	set readtree_d {} | ||||
| 	set status_bar_operation [$::main_status start \ | ||||
| 	$::main_status start \ | ||||
| 		[mc "Updating working directory to '%s'..." [_name $this]] \ | ||||
| 		[mc "files checked out"]] | ||||
| 		[mc "files checked out"] | ||||
| 
 | ||||
| 	set fd [git_read --stderr read-tree \ | ||||
| 		-m \ | ||||
|  | @ -354,27 +354,26 @@ method _readtree {} { | |||
| 		$new_hash \ | ||||
| 		] | ||||
| 	fconfigure $fd -blocking 0 -translation binary | ||||
| 	fileevent $fd readable [cb _readtree_wait $fd $status_bar_operation] | ||||
| 	fileevent $fd readable [cb _readtree_wait $fd] | ||||
| } | ||||
| 
 | ||||
| method _readtree_wait {fd status_bar_operation} { | ||||
| method _readtree_wait {fd} { | ||||
| 	global current_branch | ||||
| 
 | ||||
| 	set buf [read $fd] | ||||
| 	$status_bar_operation update_meter $buf | ||||
| 	$::main_status update_meter $buf | ||||
| 	append readtree_d $buf | ||||
| 
 | ||||
| 	fconfigure $fd -blocking 1 | ||||
| 	if {![eof $fd]} { | ||||
| 		fconfigure $fd -blocking 0 | ||||
| 		$status_bar_operation stop | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if {[catch {close $fd}]} { | ||||
| 		set err $readtree_d | ||||
| 		regsub {^fatal: } $err {} err | ||||
| 		$status_bar_operation stop [mc "Aborted checkout of '%s' (file level merging is required)." [_name $this]] | ||||
| 		$::main_status stop [mc "Aborted checkout of '%s' (file level merging is required)." [_name $this]] | ||||
| 		warn_popup [strcat [mc "File level merge required."] " | ||||
| 
 | ||||
| $err | ||||
|  | @ -385,12 +384,12 @@ $err | |||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	$status_bar_operation stop | ||||
| 	$::main_status stop | ||||
| 	_after_readtree $this | ||||
| } | ||||
| 
 | ||||
| method _after_readtree {} { | ||||
| 	global commit_type HEAD MERGE_HEAD PARENT | ||||
| 	global selected_commit_type commit_type HEAD MERGE_HEAD PARENT | ||||
| 	global current_branch is_detached | ||||
| 	global ui_comm | ||||
| 
 | ||||
|  | @ -491,12 +490,12 @@ method _update_repo_state {} { | |||
| 	#    amend mode our file lists are accurate and we can avoid | ||||
| 	#    the rescan. | ||||
| 	# | ||||
| 	global commit_type_is_amend commit_type HEAD MERGE_HEAD PARENT | ||||
| 	global selected_commit_type commit_type HEAD MERGE_HEAD PARENT | ||||
| 	global ui_comm | ||||
| 
 | ||||
| 	unlock_index | ||||
| 	set name [_name $this] | ||||
| 	set commit_type_is_amend 0 | ||||
| 	set selected_commit_type new | ||||
| 	if {[string match amend* $commit_type]} { | ||||
| 		$ui_comm delete 0.0 end | ||||
| 		$ui_comm edit reset | ||||
|  |  | |||
							
								
								
									
										120
									
								
								third_party/git/git-gui/lib/choose_repository.tcl
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										120
									
								
								third_party/git/git-gui/lib/choose_repository.tcl
									
										
									
									
										vendored
									
									
								
							|  | @ -9,18 +9,6 @@ field w_body      ; # Widget holding the center content | |||
| field w_next      ; # Next button | ||||
| field w_quit      ; # Quit button | ||||
| field o_cons      ; # Console object (if active) | ||||
| 
 | ||||
| # Status mega-widget instance during _do_clone2 (used by _copy_files and | ||||
| # _link_files). Widget is destroyed before _do_clone2 calls | ||||
| # _do_clone_checkout | ||||
| field o_status | ||||
| 
 | ||||
| # Operation displayed by status mega-widget during _do_clone_checkout => | ||||
| # _readtree_wait => _postcheckout_wait => _do_clone_submodules => | ||||
| # _do_validate_submodule_cloning. The status mega-widget is a different | ||||
| # instance than that stored in $o_status in earlier operations. | ||||
| field o_status_op | ||||
| 
 | ||||
| field w_types     ; # List of type buttons in clone | ||||
| field w_recentlist ; # Listbox containing recent repositories | ||||
| field w_localpath  ; # Entry widget bound to local_path | ||||
|  | @ -671,12 +659,12 @@ method _do_clone2 {} { | |||
| 
 | ||||
| 	switch -exact -- $clone_type { | ||||
| 	hardlink { | ||||
| 		set o_status [status_bar::two_line $w_body] | ||||
| 		set o_cons [status_bar::two_line $w_body] | ||||
| 		pack $w_body -fill x -padx 10 -pady 10 | ||||
| 
 | ||||
| 		set status_op [$o_status start \ | ||||
| 		$o_cons start \ | ||||
| 			[mc "Counting objects"] \ | ||||
| 			[mc "buckets"]] | ||||
| 			[mc "buckets"] | ||||
| 		update | ||||
| 
 | ||||
| 		if {[file exists [file join $objdir info alternates]]} { | ||||
|  | @ -701,7 +689,6 @@ method _do_clone2 {} { | |||
| 			} err]} { | ||||
| 				catch {cd $pwd} | ||||
| 				_clone_failed $this [mc "Unable to copy objects/info/alternates: %s" $err] | ||||
| 				$status_op stop | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
|  | @ -713,7 +700,7 @@ method _do_clone2 {} { | |||
| 			-directory [file join $objdir] ??] | ||||
| 		set bcnt [expr {[llength $buckets] + 2}] | ||||
| 		set bcur 1 | ||||
| 		$status_op update $bcur $bcnt | ||||
| 		$o_cons update $bcur $bcnt | ||||
| 		update | ||||
| 
 | ||||
| 		file mkdir [file join .git objects pack] | ||||
|  | @ -721,7 +708,7 @@ method _do_clone2 {} { | |||
| 			-directory [file join $objdir pack] *] { | ||||
| 			lappend tolink [file join pack $i] | ||||
| 		} | ||||
| 		$status_op update [incr bcur] $bcnt | ||||
| 		$o_cons update [incr bcur] $bcnt | ||||
| 		update | ||||
| 
 | ||||
| 		foreach i $buckets { | ||||
|  | @ -730,10 +717,10 @@ method _do_clone2 {} { | |||
| 				-directory [file join $objdir $i] *] { | ||||
| 				lappend tolink [file join $i $j] | ||||
| 			} | ||||
| 			$status_op update [incr bcur] $bcnt | ||||
| 			$o_cons update [incr bcur] $bcnt | ||||
| 			update | ||||
| 		} | ||||
| 		$status_op stop | ||||
| 		$o_cons stop | ||||
| 
 | ||||
| 		if {$tolink eq {}} { | ||||
| 			info_popup [strcat \ | ||||
|  | @ -760,8 +747,6 @@ method _do_clone2 {} { | |||
| 		if {!$i} return | ||||
| 
 | ||||
| 		destroy $w_body | ||||
| 
 | ||||
| 		set o_status {} | ||||
| 	} | ||||
| 	full { | ||||
| 		set o_cons [console::embed \ | ||||
|  | @ -796,9 +781,9 @@ method _do_clone2 {} { | |||
| } | ||||
| 
 | ||||
| method _copy_files {objdir tocopy} { | ||||
| 	set status_op [$o_status start \ | ||||
| 	$o_cons start \ | ||||
| 		[mc "Copying objects"] \ | ||||
| 		[mc "KiB"]] | ||||
| 		[mc "KiB"] | ||||
| 	set tot 0 | ||||
| 	set cmp 0 | ||||
| 	foreach p $tocopy { | ||||
|  | @ -813,7 +798,7 @@ method _copy_files {objdir tocopy} { | |||
| 
 | ||||
| 				while {![eof $f_in]} { | ||||
| 					incr cmp [fcopy $f_in $f_cp -size 16384] | ||||
| 					$status_op update \ | ||||
| 					$o_cons update \ | ||||
| 						[expr {$cmp / 1024}] \ | ||||
| 						[expr {$tot / 1024}] | ||||
| 					update | ||||
|  | @ -823,19 +808,17 @@ method _copy_files {objdir tocopy} { | |||
| 				close $f_cp | ||||
| 			} err]} { | ||||
| 			_clone_failed $this [mc "Unable to copy object: %s" $err] | ||||
| 			$status_op stop | ||||
| 			return 0 | ||||
| 		} | ||||
| 	} | ||||
| 	$status_op stop | ||||
| 	return 1 | ||||
| } | ||||
| 
 | ||||
| method _link_files {objdir tolink} { | ||||
| 	set total [llength $tolink] | ||||
| 	set status_op [$o_status start \ | ||||
| 	$o_cons start \ | ||||
| 		[mc "Linking objects"] \ | ||||
| 		[mc "objects"]] | ||||
| 		[mc "objects"] | ||||
| 	for {set i 0} {$i < $total} {} { | ||||
| 		set p [lindex $tolink $i] | ||||
| 		if {[catch { | ||||
|  | @ -844,17 +827,15 @@ method _link_files {objdir tolink} { | |||
| 					[file join $objdir $p] | ||||
| 			} err]} { | ||||
| 			_clone_failed $this [mc "Unable to hardlink object: %s" $err] | ||||
| 			$status_op stop | ||||
| 			return 0 | ||||
| 		} | ||||
| 
 | ||||
| 		incr i | ||||
| 		if {$i % 5 == 0} { | ||||
| 			$status_op update $i $total | ||||
| 			$o_cons update $i $total | ||||
| 			update | ||||
| 		} | ||||
| 	} | ||||
| 	$status_op stop | ||||
| 	return 1 | ||||
| } | ||||
| 
 | ||||
|  | @ -977,26 +958,11 @@ method _do_clone_checkout {HEAD} { | |||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	set status [status_bar::two_line $w_body] | ||||
| 	set o_cons [status_bar::two_line $w_body] | ||||
| 	pack $w_body -fill x -padx 10 -pady 10 | ||||
| 
 | ||||
| 	# We start the status operation here. | ||||
| 	# | ||||
| 	# This function calls _readtree_wait as a callback. | ||||
| 	# | ||||
| 	# _readtree_wait in turn either calls _do_clone_submodules directly, | ||||
| 	# or calls _postcheckout_wait as a callback which then calls | ||||
| 	# _do_clone_submodules. | ||||
| 	# | ||||
| 	# _do_clone_submodules calls _do_validate_submodule_cloning. | ||||
| 	# | ||||
| 	# _do_validate_submodule_cloning stops the status operation. | ||||
| 	# | ||||
| 	# There are no other calls into this chain from other code. | ||||
| 
 | ||||
| 	set o_status_op [$status start \ | ||||
| 	$o_cons start \ | ||||
| 		[mc "Creating working directory"] \ | ||||
| 		[mc "files"]] | ||||
| 		[mc "files"] | ||||
| 
 | ||||
| 	set readtree_err {} | ||||
| 	set fd [git_read --stderr read-tree \ | ||||
|  | @ -1010,9 +976,33 @@ method _do_clone_checkout {HEAD} { | |||
| 	fileevent $fd readable [cb _readtree_wait $fd] | ||||
| } | ||||
| 
 | ||||
| method _do_validate_submodule_cloning {ok} { | ||||
| 	if {$ok} { | ||||
| 		$o_cons done $ok | ||||
| 		set done 1 | ||||
| 	} else { | ||||
| 		_clone_failed $this [mc "Cannot clone submodules."] | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| method _do_clone_submodules {} { | ||||
| 	if {$recursive eq {true}} { | ||||
| 		destroy $w_body | ||||
| 		set o_cons [console::embed \ | ||||
| 			$w_body \ | ||||
| 			[mc "Cloning submodules"]] | ||||
| 		pack $w_body -fill both -expand 1 -padx 10 | ||||
| 		$o_cons exec \ | ||||
| 			[list git submodule update --init --recursive] \ | ||||
| 			[cb _do_validate_submodule_cloning] | ||||
| 	} else { | ||||
| 		set done 1 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| method _readtree_wait {fd} { | ||||
| 	set buf [read $fd] | ||||
| 	$o_status_op update_meter $buf | ||||
| 	$o_cons update_meter $buf | ||||
| 	append readtree_err $buf | ||||
| 
 | ||||
| 	fconfigure $fd -blocking 1 | ||||
|  | @ -1060,34 +1050,6 @@ method _postcheckout_wait {fd_ph} { | |||
| 	fconfigure $fd_ph -blocking 0 | ||||
| } | ||||
| 
 | ||||
| method _do_clone_submodules {} { | ||||
| 	if {$recursive eq {true}} { | ||||
| 		$o_status_op stop | ||||
| 		set o_status_op {} | ||||
| 
 | ||||
| 		destroy $w_body | ||||
| 
 | ||||
| 		set o_cons [console::embed \ | ||||
| 			$w_body \ | ||||
| 			[mc "Cloning submodules"]] | ||||
| 		pack $w_body -fill both -expand 1 -padx 10 | ||||
| 		$o_cons exec \ | ||||
| 			[list git submodule update --init --recursive] \ | ||||
| 			[cb _do_validate_submodule_cloning] | ||||
| 	} else { | ||||
| 		set done 1 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| method _do_validate_submodule_cloning {ok} { | ||||
| 	if {$ok} { | ||||
| 		$o_cons done $ok | ||||
| 		set done 1 | ||||
| 	} else { | ||||
| 		_clone_failed $this [mc "Cannot clone submodules."] | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| ###################################################################### | ||||
| ## | ||||
| ## Open Existing Repository | ||||
|  |  | |||
							
								
								
									
										158
									
								
								third_party/git/git-gui/lib/chord.tcl
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										158
									
								
								third_party/git/git-gui/lib/chord.tcl
									
										
									
									
										vendored
									
									
								
							|  | @ -1,158 +0,0 @@ | |||
| # Simple Chord for Tcl | ||||
| # | ||||
| # A "chord" is a method with more than one entrypoint and only one body, such | ||||
| # that the body runs only once all the entrypoints have been called by | ||||
| # different asynchronous tasks. In this implementation, the chord is defined | ||||
| # dynamically for each invocation. A SimpleChord object is created, supplying | ||||
| # body script to be run when the chord is completed, and then one or more notes | ||||
| # are added to the chord. Each note can be called like a proc, and returns | ||||
| # immediately if the chord isn't yet complete. When the last remaining note is | ||||
| # called, the body runs before the note returns. | ||||
| # | ||||
| # The SimpleChord class has a constructor that takes the body script, and a | ||||
| # method add_note that returns a note object. Since the body script does not | ||||
| # run in the context of the procedure that defined it, a mechanism is provided | ||||
| # for injecting variables into the chord for use by the body script. The | ||||
| # activation of a note is idempotent; multiple calls have the same effect as | ||||
| # a simple call. | ||||
| # | ||||
| # If you are invoking asynchronous operations with chord notes as completion | ||||
| # callbacks, and there is a possibility that earlier operations could complete | ||||
| # before later ones are started, it is a good practice to create a "common" | ||||
| # note on the chord that prevents it from being complete until you're certain | ||||
| # you've added all the notes you need. | ||||
| # | ||||
| # Example: | ||||
| # | ||||
| #   # Turn off the UI while running a couple of async operations. | ||||
| #   lock_ui | ||||
| # | ||||
| #   set chord [SimpleChord::new { | ||||
| #     unlock_ui | ||||
| #     # Note: $notice here is not referenced in the calling scope | ||||
| #     if {$notice} { info_popup $notice } | ||||
| #   } | ||||
| # | ||||
| #   # Configure a note to keep the chord from completing until | ||||
| #   # all operations have been initiated. | ||||
| #   set common_note [$chord add_note] | ||||
| # | ||||
| #   # Activate notes in 'after' callbacks to other operations | ||||
| #   set newnote [$chord add_note] | ||||
| #   async_operation $args [list $newnote activate] | ||||
| # | ||||
| #   # Communicate with the chord body | ||||
| #   if {$condition} { | ||||
| #     # This sets $notice in the same context that the chord body runs in. | ||||
| #     $chord eval { set notice "Something interesting" } | ||||
| #   } | ||||
| # | ||||
| #   # Activate the common note, making the chord eligible to complete | ||||
| #   $common_note activate | ||||
| # | ||||
| # At this point, the chord will complete at some unknown point in the future. | ||||
| # The common note might have been the first note activated, or the async | ||||
| # operations might have completed synchronously and the common note is the | ||||
| # last one, completing the chord before this code finishes, or anything in | ||||
| # between. The purpose of the chord is to not have to worry about the order. | ||||
| 
 | ||||
| # SimpleChord class: | ||||
| #   Represents a procedure that conceptually has multiple entrypoints that must | ||||
| #   all be called before the procedure executes. Each entrypoint is called a | ||||
| #   "note". The chord is only "completed" when all the notes are "activated". | ||||
| class SimpleChord { | ||||
| 	field notes | ||||
| 	field body | ||||
| 	field is_completed | ||||
| 	field eval_ns | ||||
| 
 | ||||
| 	# Constructor: | ||||
| 	#   set chord [SimpleChord::new {body}] | ||||
| 	#     Creates a new chord object with the specified body script. The | ||||
| 	#     body script is evaluated at most once, when a note is activated | ||||
| 	#     and the chord has no other non-activated notes. | ||||
| 	constructor new {i_body} { | ||||
| 		set notes [list] | ||||
| 		set body $i_body | ||||
| 		set is_completed 0 | ||||
| 		set eval_ns "[namespace qualifiers $this]::eval" | ||||
| 		return $this | ||||
| 	} | ||||
| 
 | ||||
| 	# Method: | ||||
| 	#   $chord eval {script} | ||||
| 	#     Runs the specified script in the same context (namespace) in which | ||||
| 	#     the chord body will be evaluated. This can be used to set variable | ||||
| 	#     values for the chord body to use. | ||||
| 	method eval {script} { | ||||
| 		namespace eval $eval_ns $script | ||||
| 	} | ||||
| 
 | ||||
| 	# Method: | ||||
| 	#   set note [$chord add_note] | ||||
| 	#     Adds a new note to the chord, an instance of ChordNote. Raises an | ||||
| 	#     error if the chord is already completed, otherwise the chord is | ||||
| 	#     updated so that the new note must also be activated before the | ||||
| 	#     body is evaluated. | ||||
| 	method add_note {} { | ||||
| 		if {$is_completed} { error "Cannot add a note to a completed chord" } | ||||
| 
 | ||||
| 		set note [ChordNote::new $this] | ||||
| 
 | ||||
| 		lappend notes $note | ||||
| 
 | ||||
| 		return $note | ||||
| 	} | ||||
| 
 | ||||
| 	# This method is for internal use only and is intentionally undocumented. | ||||
| 	method notify_note_activation {} { | ||||
| 		if {!$is_completed} { | ||||
| 			foreach note $notes { | ||||
| 				if {![$note is_activated]} { return } | ||||
| 			} | ||||
| 
 | ||||
| 			set is_completed 1 | ||||
| 
 | ||||
| 			namespace eval $eval_ns $body | ||||
| 			delete_this | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| # ChordNote class: | ||||
| #   Represents a note within a chord, providing a way to activate it. When the | ||||
| #   final note of the chord is activated (this can be any note in the chord, | ||||
| #   with all other notes already previously activated in any order), the chord's | ||||
| #   body is evaluated. | ||||
| class ChordNote { | ||||
| 	field chord | ||||
| 	field is_activated | ||||
| 
 | ||||
| 	# Constructor: | ||||
| 	#   Instances of ChordNote are created internally by calling add_note on | ||||
| 	#   SimpleChord objects. | ||||
| 	constructor new {c} { | ||||
| 		set chord $c | ||||
| 		set is_activated 0 | ||||
| 		return $this | ||||
| 	} | ||||
| 
 | ||||
| 	# Method: | ||||
| 	#   [$note is_activated] | ||||
| 	#     Returns true if this note has already been activated. | ||||
| 	method is_activated {} { | ||||
| 		return $is_activated | ||||
| 	} | ||||
| 
 | ||||
| 	# Method: | ||||
| 	#   $note activate | ||||
| 	#     Activates the note, if it has not already been activated, and | ||||
| 	#     completes the chord if there are no other notes awaiting | ||||
| 	#     activation. Subsequent calls will have no further effect. | ||||
| 	method activate {} { | ||||
| 		if {!$is_activated} { | ||||
| 			set is_activated 1 | ||||
| 			$chord notify_note_activation | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										4
									
								
								third_party/git/git-gui/lib/commit.tcl
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								third_party/git/git-gui/lib/commit.tcl
									
										
									
									
										vendored
									
									
								
							|  | @ -333,7 +333,7 @@ proc commit_writetree {curHEAD msg_p} { | |||
| proc commit_committree {fd_wt curHEAD msg_p} { | ||||
| 	global HEAD PARENT MERGE_HEAD commit_type commit_author | ||||
| 	global current_branch | ||||
| 	global ui_comm commit_type_is_amend | ||||
| 	global ui_comm selected_commit_type | ||||
| 	global file_states selected_paths rescan_active | ||||
| 	global repo_config | ||||
| 	global env | ||||
|  | @ -467,8 +467,8 @@ A rescan will be automatically started now. | |||
| 
 | ||||
| 	# -- Update in memory status | ||||
| 	# | ||||
| 	set selected_commit_type new | ||||
| 	set commit_type normal | ||||
| 	set commit_type_is_amend 0 | ||||
| 	set HEAD $cmt_id | ||||
| 	set PARENT $cmt_id | ||||
| 	set MERGE_HEAD [list] | ||||
|  |  | |||
							
								
								
									
										2
									
								
								third_party/git/git-gui/lib/console.tcl
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								third_party/git/git-gui/lib/console.tcl
									
										
									
									
										vendored
									
									
								
							|  | @ -203,8 +203,6 @@ method done {ok} { | |||
| 			focus $w.ok | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	bind $w <Key-Escape> "destroy $w;break" | ||||
| } | ||||
| 
 | ||||
| method _sb_set {sb orient first last} { | ||||
|  |  | |||
							
								
								
									
										129
									
								
								third_party/git/git-gui/lib/diff.tcl
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										129
									
								
								third_party/git/git-gui/lib/diff.tcl
									
										
									
									
										vendored
									
									
								
							|  | @ -55,7 +55,7 @@ proc reshow_diff {{after {}}} { | |||
| 
 | ||||
| proc force_diff_encoding {enc} { | ||||
| 	global current_diff_path | ||||
| 
 | ||||
| 	 | ||||
| 	if {$current_diff_path ne {}} { | ||||
| 		force_path_encoding $current_diff_path $enc | ||||
| 		reshow_diff | ||||
|  | @ -270,6 +270,19 @@ proc show_other_diff {path w m cont_info} { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| proc get_conflict_marker_size {path} { | ||||
| 	set size 7 | ||||
| 	catch { | ||||
| 		set fd_rc [eval [list git_read check-attr "conflict-marker-size" -- $path]] | ||||
| 		set ret [gets $fd_rc line] | ||||
| 		close $fd_rc | ||||
| 		if {$ret > 0} { | ||||
| 			regexp {.*: conflict-marker-size: (\d+)$} $line line size | ||||
| 		} | ||||
| 	} | ||||
| 	return $size | ||||
| } | ||||
| 
 | ||||
| proc start_show_diff {cont_info {add_opts {}}} { | ||||
| 	global file_states file_lists | ||||
| 	global is_3way_diff is_submodule_diff diff_active repo_config | ||||
|  | @ -285,7 +298,7 @@ proc start_show_diff {cont_info {add_opts {}}} { | |||
| 	set is_submodule_diff 0 | ||||
| 	set diff_active 1 | ||||
| 	set current_diff_header {} | ||||
| 	set conflict_size [gitattr $path conflict-marker-size 7] | ||||
| 	set conflict_size [get_conflict_marker_size $path] | ||||
| 
 | ||||
| 	set cmd [list] | ||||
| 	if {$w eq $ui_index} { | ||||
|  | @ -347,10 +360,6 @@ proc start_show_diff {cont_info {add_opts {}}} { | |||
| 	} | ||||
| 
 | ||||
| 	set ::current_diff_inheader 1 | ||||
| 	# Detect pre-image lines of the diff3 conflict-style. They are just | ||||
| 	# '++' lines which is not bijective. Thus, we need to maintain a state | ||||
| 	# across lines. | ||||
| 	set ::conflict_in_pre_image 0 | ||||
| 	fconfigure $fd \ | ||||
| 		-blocking 0 \ | ||||
| 		-encoding [get_path_encoding $path] \ | ||||
|  | @ -453,23 +462,11 @@ proc read_diff {fd conflict_size cont_info} { | |||
| 			{--} {set tags d_--} | ||||
| 			{++} { | ||||
| 				set regexp [string map [list %conflict_size $conflict_size]\ | ||||
| 								{^\+\+([<>=|]){%conflict_size}(?: |$)}] | ||||
| 								{^\+\+([<>=]){%conflict_size}(?: |$)}] | ||||
| 				if {[regexp $regexp $line _g op]} { | ||||
| 					set is_conflict_diff 1 | ||||
| 					set line [string replace $line 0 1 {  }] | ||||
| 					set tags d$op | ||||
| 
 | ||||
| 					# The ||| conflict-marker marks the start of the pre-image. | ||||
| 					# All those lines are also prefixed with '++'. Thus we need | ||||
| 					# to maintain this state. | ||||
| 					set ::conflict_in_pre_image [expr {$op eq {|}}] | ||||
| 				} elseif {$::conflict_in_pre_image} { | ||||
| 					# This is a pre-image line. It is the one which both sides | ||||
| 					# are based on. As it has also the '++' line start, it is | ||||
| 					# normally shown as 'added'. Invert this to '--' to make | ||||
| 					# it a 'removed' line. | ||||
| 					set line [string replace $line 0 1 {--}] | ||||
| 					set tags d_-- | ||||
| 				} else { | ||||
| 					set tags d_++ | ||||
| 				} | ||||
|  | @ -570,31 +567,24 @@ proc read_diff {fd conflict_size cont_info} { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| proc apply_or_revert_hunk {x y revert} { | ||||
| proc apply_hunk {x y} { | ||||
| 	global current_diff_path current_diff_header current_diff_side | ||||
| 	global ui_diff ui_index file_states last_revert last_revert_enc | ||||
| 	global ui_diff ui_index file_states | ||||
| 
 | ||||
| 	if {$current_diff_path eq {} || $current_diff_header eq {}} return | ||||
| 	if {![lock_index apply_hunk]} return | ||||
| 
 | ||||
| 	set apply_cmd {apply --whitespace=nowarn} | ||||
| 	set apply_cmd {apply --cached --whitespace=nowarn} | ||||
| 	set mi [lindex $file_states($current_diff_path) 0] | ||||
| 	if {$current_diff_side eq $ui_index} { | ||||
| 		set failed_msg [mc "Failed to unstage selected hunk."] | ||||
| 		lappend apply_cmd --reverse --cached | ||||
| 		lappend apply_cmd --reverse | ||||
| 		if {[string index $mi 0] ne {M}} { | ||||
| 			unlock_index | ||||
| 			return | ||||
| 		} | ||||
| 	} else { | ||||
| 		if {$revert} { | ||||
| 			set failed_msg [mc "Failed to revert selected hunk."] | ||||
| 			lappend apply_cmd --reverse | ||||
| 		} else { | ||||
| 			set failed_msg [mc "Failed to stage selected hunk."] | ||||
| 			lappend apply_cmd --cached | ||||
| 		} | ||||
| 
 | ||||
| 		set failed_msg [mc "Failed to stage selected hunk."] | ||||
| 		if {[string index $mi 1] ne {M}} { | ||||
| 			unlock_index | ||||
| 			return | ||||
|  | @ -613,40 +603,29 @@ proc apply_or_revert_hunk {x y revert} { | |||
| 		set e_lno end | ||||
| 	} | ||||
| 
 | ||||
| 	set wholepatch "$current_diff_header[$ui_diff get $s_lno $e_lno]" | ||||
| 
 | ||||
| 	if {[catch { | ||||
| 		set enc [get_path_encoding $current_diff_path] | ||||
| 		set p [eval git_write $apply_cmd] | ||||
| 		fconfigure $p -translation binary -encoding $enc | ||||
| 		puts -nonewline $p $wholepatch | ||||
| 		puts -nonewline $p $current_diff_header | ||||
| 		puts -nonewline $p [$ui_diff get $s_lno $e_lno] | ||||
| 		close $p} err]} { | ||||
| 		error_popup "$failed_msg\n\n$err" | ||||
| 		unlock_index | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if {$revert} { | ||||
| 		# Save a copy of this patch for undoing reverts. | ||||
| 		set last_revert $wholepatch | ||||
| 		set last_revert_enc $enc | ||||
| 	} | ||||
| 
 | ||||
| 	$ui_diff conf -state normal | ||||
| 	$ui_diff delete $s_lno $e_lno | ||||
| 	$ui_diff conf -state disabled | ||||
| 
 | ||||
| 	# Check if the hunk was the last one in the file. | ||||
| 	if {[$ui_diff get 1.0 end] eq "\n"} { | ||||
| 		set o _ | ||||
| 	} else { | ||||
| 		set o ? | ||||
| 	} | ||||
| 
 | ||||
| 	# Update the status flags. | ||||
| 	if {$revert} { | ||||
| 		set mi [string index $mi 0]$o | ||||
| 	} elseif {$current_diff_side eq $ui_index} { | ||||
| 	if {$current_diff_side eq $ui_index} { | ||||
| 		set mi ${o}M | ||||
| 	} elseif {[string index $mi 0] eq {_}} { | ||||
| 		set mi M$o | ||||
|  | @ -661,9 +640,9 @@ proc apply_or_revert_hunk {x y revert} { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| proc apply_or_revert_range_or_line {x y revert} { | ||||
| proc apply_range_or_line {x y} { | ||||
| 	global current_diff_path current_diff_header current_diff_side | ||||
| 	global ui_diff ui_index file_states last_revert | ||||
| 	global ui_diff ui_index file_states | ||||
| 
 | ||||
| 	set selected [$ui_diff tag nextrange sel 0.0] | ||||
| 
 | ||||
|  | @ -681,27 +660,19 @@ proc apply_or_revert_range_or_line {x y revert} { | |||
| 	if {$current_diff_path eq {} || $current_diff_header eq {}} return | ||||
| 	if {![lock_index apply_hunk]} return | ||||
| 
 | ||||
| 	set apply_cmd {apply --whitespace=nowarn} | ||||
| 	set apply_cmd {apply --cached --whitespace=nowarn} | ||||
| 	set mi [lindex $file_states($current_diff_path) 0] | ||||
| 	if {$current_diff_side eq $ui_index} { | ||||
| 		set failed_msg [mc "Failed to unstage selected line."] | ||||
| 		set to_context {+} | ||||
| 		lappend apply_cmd --reverse --cached | ||||
| 		lappend apply_cmd --reverse | ||||
| 		if {[string index $mi 0] ne {M}} { | ||||
| 			unlock_index | ||||
| 			return | ||||
| 		} | ||||
| 	} else { | ||||
| 		if {$revert} { | ||||
| 			set failed_msg [mc "Failed to revert selected line."] | ||||
| 			set to_context {+} | ||||
| 			lappend apply_cmd --reverse | ||||
| 		} else { | ||||
| 			set failed_msg [mc "Failed to stage selected line."] | ||||
| 			set to_context {-} | ||||
| 			lappend apply_cmd --cached | ||||
| 		} | ||||
| 
 | ||||
| 		set failed_msg [mc "Failed to stage selected line."] | ||||
| 		set to_context {-} | ||||
| 		if {[string index $mi 1] ne {M}} { | ||||
| 			unlock_index | ||||
| 			return | ||||
|  | @ -859,47 +830,7 @@ proc apply_or_revert_range_or_line {x y revert} { | |||
| 		puts -nonewline $p $wholepatch | ||||
| 		close $p} err]} { | ||||
| 		error_popup "$failed_msg\n\n$err" | ||||
| 		unlock_index | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if {$revert} { | ||||
| 		# Save a copy of this patch for undoing reverts. | ||||
| 		set last_revert $current_diff_header$wholepatch | ||||
| 		set last_revert_enc $enc | ||||
| 	} | ||||
| 
 | ||||
| 	unlock_index | ||||
| } | ||||
| 
 | ||||
| # Undo the last line/hunk reverted. When hunks and lines are reverted, a copy | ||||
| # of the diff applied is saved. Re-apply that diff to undo the revert. | ||||
| # | ||||
| # Right now, we only use a single variable to hold the copy, and not a | ||||
| # stack/deque for simplicity, so multiple undos are not possible. Maybe this | ||||
| # can be added if the need for something like this is felt in the future. | ||||
| proc undo_last_revert {} { | ||||
| 	global last_revert current_diff_path current_diff_header | ||||
| 	global last_revert_enc | ||||
| 
 | ||||
| 	if {$last_revert eq {}} return | ||||
| 	if {![lock_index apply_hunk]} return | ||||
| 
 | ||||
| 	set apply_cmd {apply --whitespace=nowarn} | ||||
| 	set failed_msg [mc "Failed to undo last revert."] | ||||
| 
 | ||||
| 	if {[catch { | ||||
| 		set enc $last_revert_enc | ||||
| 		set p [eval git_write $apply_cmd] | ||||
| 		fconfigure $p -translation binary -encoding $enc | ||||
| 		puts -nonewline $p $last_revert | ||||
| 		close $p} err]} { | ||||
| 		error_popup "$failed_msg\n\n$err" | ||||
| 		unlock_index | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	set last_revert {} | ||||
| 
 | ||||
| 	unlock_index | ||||
| } | ||||
|  |  | |||
							
								
								
									
										529
									
								
								third_party/git/git-gui/lib/index.tcl
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										529
									
								
								third_party/git/git-gui/lib/index.tcl
									
										
									
									
										vendored
									
									
								
							|  | @ -7,74 +7,67 @@ proc _delete_indexlock {} { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| proc close_and_unlock_index {fd after} { | ||||
| 	if {![catch {_close_updateindex $fd} err]} { | ||||
| 		unlock_index | ||||
| 		uplevel #0 $after | ||||
| 	} else { | ||||
| 		rescan_on_error $err $after | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| proc _close_updateindex {fd} { | ||||
| 	fconfigure $fd -blocking 1 | ||||
| 	close $fd | ||||
| } | ||||
| 
 | ||||
| proc rescan_on_error {err {after {}}} { | ||||
| proc _close_updateindex {fd after} { | ||||
| 	global use_ttk NS | ||||
| 	fconfigure $fd -blocking 1 | ||||
| 	if {[catch {close $fd} err]} { | ||||
| 		set w .indexfried | ||||
| 		Dialog $w | ||||
| 		wm withdraw $w | ||||
| 		wm title $w [strcat "[appname] ([reponame]): " [mc "Index Error"]] | ||||
| 		wm geometry $w "+[winfo rootx .]+[winfo rooty .]" | ||||
| 		set s [mc "Updating the Git index failed.  A rescan will be automatically started to resynchronize git-gui."] | ||||
| 		text $w.msg -yscrollcommand [list $w.vs set] \ | ||||
| 			-width [string length $s] -relief flat \ | ||||
| 			-borderwidth 0 -highlightthickness 0 \ | ||||
| 			-background [get_bg_color $w] | ||||
| 		$w.msg tag configure bold -font font_uibold -justify center | ||||
| 		${NS}::scrollbar $w.vs -command [list $w.msg yview] | ||||
| 		$w.msg insert end $s bold \n\n$err {} | ||||
| 		$w.msg configure -state disabled | ||||
| 
 | ||||
| 	set w .indexfried | ||||
| 	Dialog $w | ||||
| 	wm withdraw $w | ||||
| 	wm title $w [strcat "[appname] ([reponame]): " [mc "Index Error"]] | ||||
| 	wm geometry $w "+[winfo rootx .]+[winfo rooty .]" | ||||
| 	set s [mc "Updating the Git index failed.  A rescan will be automatically started to resynchronize git-gui."] | ||||
| 	text $w.msg -yscrollcommand [list $w.vs set] \ | ||||
| 		-width [string length $s] -relief flat \ | ||||
| 		-borderwidth 0 -highlightthickness 0 \ | ||||
| 		-background [get_bg_color $w] | ||||
| 	$w.msg tag configure bold -font font_uibold -justify center | ||||
| 	${NS}::scrollbar $w.vs -command [list $w.msg yview] | ||||
| 	$w.msg insert end $s bold \n\n$err {} | ||||
| 	$w.msg configure -state disabled | ||||
| 		${NS}::button $w.continue \ | ||||
| 			-text [mc "Continue"] \ | ||||
| 			-command [list destroy $w] | ||||
| 		${NS}::button $w.unlock \ | ||||
| 			-text [mc "Unlock Index"] \ | ||||
| 			-command "destroy $w; _delete_indexlock" | ||||
| 		grid $w.msg - $w.vs -sticky news | ||||
| 		grid $w.unlock $w.continue - -sticky se -padx 2 -pady 2 | ||||
| 		grid columnconfigure $w 0 -weight 1 | ||||
| 		grid rowconfigure $w 0 -weight 1 | ||||
| 
 | ||||
| 	${NS}::button $w.continue \ | ||||
| 		-text [mc "Continue"] \ | ||||
| 		-command [list destroy $w] | ||||
| 	${NS}::button $w.unlock \ | ||||
| 		-text [mc "Unlock Index"] \ | ||||
| 		-command "destroy $w; _delete_indexlock" | ||||
| 	grid $w.msg - $w.vs -sticky news | ||||
| 	grid $w.unlock $w.continue - -sticky se -padx 2 -pady 2 | ||||
| 	grid columnconfigure $w 0 -weight 1 | ||||
| 	grid rowconfigure $w 0 -weight 1 | ||||
| 		wm protocol $w WM_DELETE_WINDOW update | ||||
| 		bind $w.continue <Visibility> " | ||||
| 			grab $w | ||||
| 			focus %W | ||||
| 		" | ||||
| 		wm deiconify $w | ||||
| 		tkwait window $w | ||||
| 
 | ||||
| 	wm protocol $w WM_DELETE_WINDOW update | ||||
| 	bind $w.continue <Visibility> " | ||||
| 		grab $w | ||||
| 		focus %W | ||||
| 	" | ||||
| 	wm deiconify $w | ||||
| 	tkwait window $w | ||||
| 		$::main_status stop | ||||
| 		unlock_index | ||||
| 		rescan $after 0 | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	$::main_status stop_all | ||||
| 	$::main_status stop | ||||
| 	unlock_index | ||||
| 	rescan [concat $after [list ui_ready]] 0 | ||||
| 	uplevel #0 $after | ||||
| } | ||||
| 
 | ||||
| proc update_indexinfo {msg path_list after} { | ||||
| proc update_indexinfo {msg pathList after} { | ||||
| 	global update_index_cp | ||||
| 
 | ||||
| 	if {![lock_index update]} return | ||||
| 
 | ||||
| 	set update_index_cp 0 | ||||
| 	set path_list [lsort $path_list] | ||||
| 	set total_cnt [llength $path_list] | ||||
| 	set batch [expr {int($total_cnt * .01) + 1}] | ||||
| 	set pathList [lsort $pathList] | ||||
| 	set totalCnt [llength $pathList] | ||||
| 	set batch [expr {int($totalCnt * .01) + 1}] | ||||
| 	if {$batch > 25} {set batch 25} | ||||
| 
 | ||||
| 	set status_bar_operation [$::main_status start $msg [mc "files"]] | ||||
| 	$::main_status start $msg [mc "files"] | ||||
| 	set fd [git_write update-index -z --index-info] | ||||
| 	fconfigure $fd \ | ||||
| 		-blocking 0 \ | ||||
|  | @ -85,29 +78,26 @@ proc update_indexinfo {msg path_list after} { | |||
| 	fileevent $fd writable [list \ | ||||
| 		write_update_indexinfo \ | ||||
| 		$fd \ | ||||
| 		$path_list \ | ||||
| 		$total_cnt \ | ||||
| 		$pathList \ | ||||
| 		$totalCnt \ | ||||
| 		$batch \ | ||||
| 		$status_bar_operation \ | ||||
| 		$after \ | ||||
| 		] | ||||
| } | ||||
| 
 | ||||
| proc write_update_indexinfo {fd path_list total_cnt batch status_bar_operation \ | ||||
| 	after} { | ||||
| proc write_update_indexinfo {fd pathList totalCnt batch after} { | ||||
| 	global update_index_cp | ||||
| 	global file_states current_diff_path | ||||
| 
 | ||||
| 	if {$update_index_cp >= $total_cnt} { | ||||
| 		$status_bar_operation stop | ||||
| 		close_and_unlock_index $fd $after | ||||
| 	if {$update_index_cp >= $totalCnt} { | ||||
| 		_close_updateindex $fd $after | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	for {set i $batch} \ | ||||
| 		{$update_index_cp < $total_cnt && $i > 0} \ | ||||
| 		{$update_index_cp < $totalCnt && $i > 0} \ | ||||
| 		{incr i -1} { | ||||
| 		set path [lindex $path_list $update_index_cp] | ||||
| 		set path [lindex $pathList $update_index_cp] | ||||
| 		incr update_index_cp | ||||
| 
 | ||||
| 		set s $file_states($path) | ||||
|  | @ -129,21 +119,21 @@ proc write_update_indexinfo {fd path_list total_cnt batch status_bar_operation \ | |||
| 		display_file $path $new | ||||
| 	} | ||||
| 
 | ||||
| 	$status_bar_operation update $update_index_cp $total_cnt | ||||
| 	$::main_status update $update_index_cp $totalCnt | ||||
| } | ||||
| 
 | ||||
| proc update_index {msg path_list after} { | ||||
| proc update_index {msg pathList after} { | ||||
| 	global update_index_cp | ||||
| 
 | ||||
| 	if {![lock_index update]} return | ||||
| 
 | ||||
| 	set update_index_cp 0 | ||||
| 	set path_list [lsort $path_list] | ||||
| 	set total_cnt [llength $path_list] | ||||
| 	set batch [expr {int($total_cnt * .01) + 1}] | ||||
| 	set pathList [lsort $pathList] | ||||
| 	set totalCnt [llength $pathList] | ||||
| 	set batch [expr {int($totalCnt * .01) + 1}] | ||||
| 	if {$batch > 25} {set batch 25} | ||||
| 
 | ||||
| 	set status_bar_operation [$::main_status start $msg [mc "files"]] | ||||
| 	$::main_status start $msg [mc "files"] | ||||
| 	set fd [git_write update-index --add --remove -z --stdin] | ||||
| 	fconfigure $fd \ | ||||
| 		-blocking 0 \ | ||||
|  | @ -154,29 +144,26 @@ proc update_index {msg path_list after} { | |||
| 	fileevent $fd writable [list \ | ||||
| 		write_update_index \ | ||||
| 		$fd \ | ||||
| 		$path_list \ | ||||
| 		$total_cnt \ | ||||
| 		$pathList \ | ||||
| 		$totalCnt \ | ||||
| 		$batch \ | ||||
| 		$status_bar_operation \ | ||||
| 		$after \ | ||||
| 		] | ||||
| } | ||||
| 
 | ||||
| proc write_update_index {fd path_list total_cnt batch status_bar_operation \ | ||||
| 	after} { | ||||
| proc write_update_index {fd pathList totalCnt batch after} { | ||||
| 	global update_index_cp | ||||
| 	global file_states current_diff_path | ||||
| 
 | ||||
| 	if {$update_index_cp >= $total_cnt} { | ||||
| 		$status_bar_operation stop | ||||
| 		close_and_unlock_index $fd $after | ||||
| 	if {$update_index_cp >= $totalCnt} { | ||||
| 		_close_updateindex $fd $after | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	for {set i $batch} \ | ||||
| 		{$update_index_cp < $total_cnt && $i > 0} \ | ||||
| 		{$update_index_cp < $totalCnt && $i > 0} \ | ||||
| 		{incr i -1} { | ||||
| 		set path [lindex $path_list $update_index_cp] | ||||
| 		set path [lindex $pathList $update_index_cp] | ||||
| 		incr update_index_cp | ||||
| 
 | ||||
| 		switch -glob -- [lindex $file_states($path) 0] { | ||||
|  | @ -203,21 +190,21 @@ proc write_update_index {fd path_list total_cnt batch status_bar_operation \ | |||
| 		display_file $path $new | ||||
| 	} | ||||
| 
 | ||||
| 	$status_bar_operation update $update_index_cp $total_cnt | ||||
| 	$::main_status update $update_index_cp $totalCnt | ||||
| } | ||||
| 
 | ||||
| proc checkout_index {msg path_list after capture_error} { | ||||
| proc checkout_index {msg pathList after} { | ||||
| 	global update_index_cp | ||||
| 
 | ||||
| 	if {![lock_index update]} return | ||||
| 
 | ||||
| 	set update_index_cp 0 | ||||
| 	set path_list [lsort $path_list] | ||||
| 	set total_cnt [llength $path_list] | ||||
| 	set batch [expr {int($total_cnt * .01) + 1}] | ||||
| 	set pathList [lsort $pathList] | ||||
| 	set totalCnt [llength $pathList] | ||||
| 	set batch [expr {int($totalCnt * .01) + 1}] | ||||
| 	if {$batch > 25} {set batch 25} | ||||
| 
 | ||||
| 	set status_bar_operation [$::main_status start $msg [mc "files"]] | ||||
| 	$::main_status start $msg [mc "files"] | ||||
| 	set fd [git_write checkout-index \ | ||||
| 		--index \ | ||||
| 		--quiet \ | ||||
|  | @ -234,45 +221,26 @@ proc checkout_index {msg path_list after capture_error} { | |||
| 	fileevent $fd writable [list \ | ||||
| 		write_checkout_index \ | ||||
| 		$fd \ | ||||
| 		$path_list \ | ||||
| 		$total_cnt \ | ||||
| 		$pathList \ | ||||
| 		$totalCnt \ | ||||
| 		$batch \ | ||||
| 		$status_bar_operation \ | ||||
| 		$after \ | ||||
| 		$capture_error \ | ||||
| 		] | ||||
| } | ||||
| 
 | ||||
| proc write_checkout_index {fd path_list total_cnt batch status_bar_operation \ | ||||
| 	after capture_error} { | ||||
| proc write_checkout_index {fd pathList totalCnt batch after} { | ||||
| 	global update_index_cp | ||||
| 	global file_states current_diff_path | ||||
| 
 | ||||
| 	if {$update_index_cp >= $total_cnt} { | ||||
| 		$status_bar_operation stop | ||||
| 
 | ||||
| 		# We do not unlock the index directly here because this | ||||
| 		# operation expects to potentially run in parallel with file | ||||
| 		# deletions scheduled by revert_helper. We're done with the | ||||
| 		# update index, so we close it, but actually unlocking the index | ||||
| 		# and dealing with potential errors is deferred to the chord | ||||
| 		# body that runs when all async operations are completed. | ||||
| 		# | ||||
| 		# (See after_chord in revert_helper.) | ||||
| 
 | ||||
| 		if {[catch {_close_updateindex $fd} err]} { | ||||
| 			uplevel #0 $capture_error [list $err] | ||||
| 		} | ||||
| 
 | ||||
| 		uplevel #0 $after | ||||
| 
 | ||||
| 	if {$update_index_cp >= $totalCnt} { | ||||
| 		_close_updateindex $fd $after | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	for {set i $batch} \ | ||||
| 		{$update_index_cp < $total_cnt && $i > 0} \ | ||||
| 		{$update_index_cp < $totalCnt && $i > 0} \ | ||||
| 		{incr i -1} { | ||||
| 		set path [lindex $path_list $update_index_cp] | ||||
| 		set path [lindex $pathList $update_index_cp] | ||||
| 		incr update_index_cp | ||||
| 		switch -glob -- [lindex $file_states($path) 0] { | ||||
| 		U? {continue} | ||||
|  | @ -285,7 +253,7 @@ proc write_checkout_index {fd path_list total_cnt batch status_bar_operation \ | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	$status_bar_operation update $update_index_cp $total_cnt | ||||
| 	$::main_status update $update_index_cp $totalCnt | ||||
| } | ||||
| 
 | ||||
| proc unstage_helper {txt paths} { | ||||
|  | @ -293,7 +261,7 @@ proc unstage_helper {txt paths} { | |||
| 
 | ||||
| 	if {![lock_index begin-update]} return | ||||
| 
 | ||||
| 	set path_list [list] | ||||
| 	set pathList [list] | ||||
| 	set after {} | ||||
| 	foreach path $paths { | ||||
| 		switch -glob -- [lindex $file_states($path) 0] { | ||||
|  | @ -301,19 +269,19 @@ proc unstage_helper {txt paths} { | |||
| 		M? - | ||||
| 		T? - | ||||
| 		D? { | ||||
| 			lappend path_list $path | ||||
| 			lappend pathList $path | ||||
| 			if {$path eq $current_diff_path} { | ||||
| 				set after {reshow_diff;} | ||||
| 			} | ||||
| 		} | ||||
| 		} | ||||
| 	} | ||||
| 	if {$path_list eq {}} { | ||||
| 	if {$pathList eq {}} { | ||||
| 		unlock_index | ||||
| 	} else { | ||||
| 		update_indexinfo \ | ||||
| 			$txt \ | ||||
| 			$path_list \ | ||||
| 			$pathList \ | ||||
| 			[concat $after [list ui_ready]] | ||||
| 	} | ||||
| } | ||||
|  | @ -337,7 +305,7 @@ proc add_helper {txt paths} { | |||
| 
 | ||||
| 	if {![lock_index begin-update]} return | ||||
| 
 | ||||
| 	set path_list [list] | ||||
| 	set pathList [list] | ||||
| 	set after {} | ||||
| 	foreach path $paths { | ||||
| 		switch -glob -- [lindex $file_states($path) 0] { | ||||
|  | @ -353,19 +321,19 @@ proc add_helper {txt paths} { | |||
| 		?M - | ||||
| 		?D - | ||||
| 		?T { | ||||
| 			lappend path_list $path | ||||
| 			lappend pathList $path | ||||
| 			if {$path eq $current_diff_path} { | ||||
| 				set after {reshow_diff;} | ||||
| 			} | ||||
| 		} | ||||
| 		} | ||||
| 	} | ||||
| 	if {$path_list eq {}} { | ||||
| 	if {$pathList eq {}} { | ||||
| 		unlock_index | ||||
| 	} else { | ||||
| 		update_index \ | ||||
| 			$txt \ | ||||
| 			$path_list \ | ||||
| 			$pathList \ | ||||
| 			[concat $after {ui_status [mc "Ready to commit."]}] | ||||
| 	} | ||||
| } | ||||
|  | @ -420,303 +388,66 @@ proc do_add_all {} { | |||
| 	add_helper [mc "Adding all changed files"] $paths | ||||
| } | ||||
| 
 | ||||
| # Copied from TclLib package "lambda". | ||||
| proc lambda {arguments body args} { | ||||
| 	return [list ::apply [list $arguments $body] {*}$args] | ||||
| } | ||||
| 
 | ||||
| proc revert_helper {txt paths} { | ||||
| 	global file_states current_diff_path | ||||
| 
 | ||||
| 	if {![lock_index begin-update]} return | ||||
| 
 | ||||
| 	# Common "after" functionality that waits until multiple asynchronous | ||||
| 	# operations are complete (by waiting for them to activate their notes | ||||
| 	# on the chord). | ||||
| 	# | ||||
| 	# The asynchronous operations are each indicated below by a comment | ||||
| 	# before the code block that starts the async operation. | ||||
| 	set after_chord [SimpleChord::new { | ||||
| 		if {[string trim $err] != ""} { | ||||
| 			rescan_on_error $err | ||||
| 		} else { | ||||
| 			unlock_index | ||||
| 			if {$should_reshow_diff} { reshow_diff } | ||||
| 			ui_ready | ||||
| 		} | ||||
| 	}] | ||||
| 
 | ||||
| 	$after_chord eval { set should_reshow_diff 0 } | ||||
| 
 | ||||
| 	# This function captures an error for processing when after_chord is | ||||
| 	# completed. (The chord is curried into the lambda function.) | ||||
| 	set capture_error [lambda \ | ||||
| 		{chord error} \ | ||||
| 		{ $chord eval [list set err $error] } \ | ||||
| 		$after_chord] | ||||
| 
 | ||||
| 	# We don't know how many notes we're going to create (it's dynamic based | ||||
| 	# on conditional paths below), so create a common note that will delay | ||||
| 	# the chord's completion until we activate it, and then activate it | ||||
| 	# after all the other notes have been created. | ||||
| 	set after_common_note [$after_chord add_note] | ||||
| 
 | ||||
| 	set path_list [list] | ||||
| 	set untracked_list [list] | ||||
| 
 | ||||
| 	set pathList [list] | ||||
| 	set after {} | ||||
| 	foreach path $paths { | ||||
| 		switch -glob -- [lindex $file_states($path) 0] { | ||||
| 		U? {continue} | ||||
| 		?O { | ||||
| 			lappend untracked_list $path | ||||
| 		} | ||||
| 		?M - | ||||
| 		?T - | ||||
| 		?D { | ||||
| 			lappend path_list $path | ||||
| 			lappend pathList $path | ||||
| 			if {$path eq $current_diff_path} { | ||||
| 				$after_chord eval { set should_reshow_diff 1 } | ||||
| 				set after {reshow_diff;} | ||||
| 			} | ||||
| 		} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	set path_cnt [llength $path_list] | ||||
| 	set untracked_cnt [llength $untracked_list] | ||||
| 
 | ||||
| 	# Asynchronous operation: revert changes by checking them out afresh | ||||
| 	# from the index. | ||||
| 	if {$path_cnt > 0} { | ||||
| 		# Split question between singular and plural cases, because | ||||
| 		# such distinction is needed in some languages. Previously, the | ||||
| 		# code used "Revert changes in" for both, but that can't work | ||||
| 		# in languages where 'in' must be combined with word from | ||||
| 		# rest of string (in different way for both cases of course). | ||||
| 		# | ||||
| 		# FIXME: Unfortunately, even that isn't enough in some languages | ||||
| 		# as they have quite complex plural-form rules. Unfortunately, | ||||
| 		# msgcat doesn't seem to support that kind of string | ||||
| 		# translation. | ||||
| 		# | ||||
| 		if {$path_cnt == 1} { | ||||
| 			set query [mc \ | ||||
| 				"Revert changes in file %s?" \ | ||||
| 				[short_path [lindex $path_list]] \ | ||||
| 				] | ||||
| 		} else { | ||||
| 			set query [mc \ | ||||
| 				"Revert changes in these %i files?" \ | ||||
| 				$path_cnt] | ||||
| 		} | ||||
| 	# Split question between singular and plural cases, because | ||||
| 	# such distinction is needed in some languages. Previously, the | ||||
| 	# code used "Revert changes in" for both, but that can't work | ||||
| 	# in languages where 'in' must be combined with word from | ||||
| 	# rest of string (in different way for both cases of course). | ||||
| 	# | ||||
| 	# FIXME: Unfortunately, even that isn't enough in some languages | ||||
| 	# as they have quite complex plural-form rules. Unfortunately, | ||||
| 	# msgcat doesn't seem to support that kind of string translation. | ||||
| 	# | ||||
| 	set n [llength $pathList] | ||||
| 	if {$n == 0} { | ||||
| 		unlock_index | ||||
| 		return | ||||
| 	} elseif {$n == 1} { | ||||
| 		set query [mc "Revert changes in file %s?" [short_path [lindex $pathList]]] | ||||
| 	} else { | ||||
| 		set query [mc "Revert changes in these %i files?" $n] | ||||
| 	} | ||||
| 
 | ||||
| 		set reply [tk_dialog \ | ||||
| 			.confirm_revert \ | ||||
| 			"[appname] ([reponame])" \ | ||||
| 			"$query | ||||
| 	set reply [tk_dialog \ | ||||
| 		.confirm_revert \ | ||||
| 		"[appname] ([reponame])" \ | ||||
| 		"$query | ||||
| 
 | ||||
| [mc "Any unstaged changes will be permanently lost by the revert."]" \ | ||||
| 			question \ | ||||
| 			1 \ | ||||
| 			[mc "Do Nothing"] \ | ||||
| 			[mc "Revert Changes"] \ | ||||
| 			] | ||||
| 
 | ||||
| 		if {$reply == 1} { | ||||
| 			set note [$after_chord add_note] | ||||
| 			checkout_index \ | ||||
| 				$txt \ | ||||
| 				$path_list \ | ||||
| 				[list $note activate] \ | ||||
| 				$capture_error | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	# Asynchronous operation: Deletion of untracked files. | ||||
| 	if {$untracked_cnt > 0} { | ||||
| 		# Split question between singular and plural cases, because | ||||
| 		# such distinction is needed in some languages. | ||||
| 		# | ||||
| 		# FIXME: Unfortunately, even that isn't enough in some languages | ||||
| 		# as they have quite complex plural-form rules. Unfortunately, | ||||
| 		# msgcat doesn't seem to support that kind of string | ||||
| 		# translation. | ||||
| 		# | ||||
| 		if {$untracked_cnt == 1} { | ||||
| 			set query [mc \ | ||||
| 				"Delete untracked file %s?" \ | ||||
| 				[short_path [lindex $untracked_list]] \ | ||||
| 				] | ||||
| 		} else { | ||||
| 			set query [mc \ | ||||
| 				"Delete these %i untracked files?" \ | ||||
| 				$untracked_cnt \ | ||||
| 				] | ||||
| 		} | ||||
| 
 | ||||
| 		set reply [tk_dialog \ | ||||
| 			.confirm_revert \ | ||||
| 			"[appname] ([reponame])" \ | ||||
| 			"$query | ||||
| 
 | ||||
| [mc "Files will be permanently deleted."]" \ | ||||
| 			question \ | ||||
| 			1 \ | ||||
| 			[mc "Do Nothing"] \ | ||||
| 			[mc "Delete Files"] \ | ||||
| 			] | ||||
| 
 | ||||
| 		if {$reply == 1} { | ||||
| 			$after_chord eval { set should_reshow_diff 1 } | ||||
| 
 | ||||
| 			set note [$after_chord add_note] | ||||
| 			delete_files $untracked_list [list $note activate] | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	# Activate the common note. If no other notes were created, this | ||||
| 	# completes the chord. If other notes were created, then this common | ||||
| 	# note prevents a race condition where the chord might complete early. | ||||
| 	$after_common_note activate | ||||
| } | ||||
| 
 | ||||
| # Delete all of the specified files, performing deletion in batches to allow the | ||||
| # UI to remain responsive and updated. | ||||
| proc delete_files {path_list after} { | ||||
| 	# Enable progress bar status updates | ||||
| 	set status_bar_operation [$::main_status \ | ||||
| 		start \ | ||||
| 		[mc "Deleting"] \ | ||||
| 		[mc "files"]] | ||||
| 
 | ||||
| 	set path_index 0 | ||||
| 	set deletion_errors [list] | ||||
| 	set batch_size 50 | ||||
| 
 | ||||
| 	delete_helper \ | ||||
| 		$path_list \ | ||||
| 		$path_index \ | ||||
| 		$deletion_errors \ | ||||
| 		$batch_size \ | ||||
| 		$status_bar_operation \ | ||||
| 		$after | ||||
| } | ||||
| 
 | ||||
| # Helper function to delete a list of files in batches. Each call deletes one | ||||
| # batch of files, and then schedules a call for the next batch after any UI | ||||
| # messages have been processed. | ||||
| proc delete_helper {path_list path_index deletion_errors batch_size \ | ||||
| 	status_bar_operation after} { | ||||
| 	global file_states | ||||
| 
 | ||||
| 	set path_cnt [llength $path_list] | ||||
| 
 | ||||
| 	set batch_remaining $batch_size | ||||
| 
 | ||||
| 	while {$batch_remaining > 0} { | ||||
| 		if {$path_index >= $path_cnt} { break } | ||||
| 
 | ||||
| 		set path [lindex $path_list $path_index] | ||||
| 
 | ||||
| 		set deletion_failed [catch {file delete -- $path} deletion_error] | ||||
| 
 | ||||
| 		if {$deletion_failed} { | ||||
| 			lappend deletion_errors [list "$deletion_error"] | ||||
| 		} else { | ||||
| 			remove_empty_directories [file dirname $path] | ||||
| 
 | ||||
| 			# Don't assume the deletion worked. Remove the file from | ||||
| 			# the UI, but only if it no longer exists. | ||||
| 			if {![path_exists $path]} { | ||||
| 				unset file_states($path) | ||||
| 				display_file $path __ | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		incr path_index 1 | ||||
| 		incr batch_remaining -1 | ||||
| 	} | ||||
| 
 | ||||
| 	# Update the progress bar to indicate that this batch has been | ||||
| 	# completed. The update will be visible when this procedure returns | ||||
| 	# and allows the UI thread to process messages. | ||||
| 	$status_bar_operation update $path_index $path_cnt | ||||
| 
 | ||||
| 	if {$path_index < $path_cnt} { | ||||
| 		# The Tcler's Wiki lists this as the best practice for keeping | ||||
| 		# a UI active and processing messages during a long-running | ||||
| 		# operation. | ||||
| 
 | ||||
| 		after idle [list after 0 [list \ | ||||
| 			delete_helper \ | ||||
| 			$path_list \ | ||||
| 			$path_index \ | ||||
| 			$deletion_errors \ | ||||
| 			$batch_size \ | ||||
| 			$status_bar_operation \ | ||||
| 			$after | ||||
| 			]] | ||||
| 		question \ | ||||
| 		1 \ | ||||
| 		[mc "Do Nothing"] \ | ||||
| 		[mc "Revert Changes"] \ | ||||
| 		] | ||||
| 	if {$reply == 1} { | ||||
| 		checkout_index \ | ||||
| 			$txt \ | ||||
| 			$pathList \ | ||||
| 			[concat $after [list ui_ready]] | ||||
| 	} else { | ||||
| 		# Finish the status bar operation. | ||||
| 		$status_bar_operation stop | ||||
| 
 | ||||
| 		# Report error, if any, based on how many deletions failed. | ||||
| 		set deletion_error_cnt [llength $deletion_errors] | ||||
| 
 | ||||
| 		if {($deletion_error_cnt > 0) | ||||
| 		 && ($deletion_error_cnt <= [MAX_VERBOSE_FILES_IN_DELETION_ERROR])} { | ||||
| 			set error_text [mc "Encountered errors deleting files:\n"] | ||||
| 
 | ||||
| 			foreach deletion_error $deletion_errors { | ||||
| 				append error_text "* [lindex $deletion_error 0]\n" | ||||
| 			} | ||||
| 
 | ||||
| 			error_popup $error_text | ||||
| 		} elseif {$deletion_error_cnt == $path_cnt} { | ||||
| 			error_popup [mc \ | ||||
| 				"None of the %d selected files could be deleted." \ | ||||
| 				$path_cnt \ | ||||
| 				] | ||||
| 		} elseif {$deletion_error_cnt > 1} { | ||||
| 			error_popup [mc \ | ||||
| 				"%d of the %d selected files could not be deleted." \ | ||||
| 				$deletion_error_cnt \ | ||||
| 				$path_cnt \ | ||||
| 				] | ||||
| 		} | ||||
| 
 | ||||
| 		uplevel #0 $after | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| proc MAX_VERBOSE_FILES_IN_DELETION_ERROR {} { return 10; } | ||||
| 
 | ||||
| # This function is from the TCL documentation: | ||||
| # | ||||
| #   https://wiki.tcl-lang.org/page/file+exists | ||||
| # | ||||
| # [file exists] returns false if the path does exist but is a symlink to a path | ||||
| # that doesn't exist. This proc returns true if the path exists, regardless of | ||||
| # whether it is a symlink and whether it is broken. | ||||
| proc path_exists {name} { | ||||
| 	expr {![catch {file lstat $name finfo}]} | ||||
| } | ||||
| 
 | ||||
| # Remove as many empty directories as we can starting at the specified path, | ||||
| # walking up the directory tree. If we encounter a directory that is not | ||||
| # empty, or if a directory deletion fails, then we stop the operation and | ||||
| # return to the caller. Even if this procedure fails to delete any | ||||
| # directories at all, it does not report failure. | ||||
| proc remove_empty_directories {directory_path} { | ||||
| 	set parent_path [file dirname $directory_path] | ||||
| 
 | ||||
| 	while {$parent_path != $directory_path} { | ||||
| 		set contents [glob -nocomplain -dir $directory_path *] | ||||
| 
 | ||||
| 		if {[llength $contents] > 0} { break } | ||||
| 		if {[catch {file delete -- $directory_path}]} { break } | ||||
| 
 | ||||
| 		set directory_path $parent_path | ||||
| 		set parent_path [file dirname $directory_path] | ||||
| 		unlock_index | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -735,19 +466,19 @@ proc do_revert_selection {} { | |||
| } | ||||
| 
 | ||||
| proc do_select_commit_type {} { | ||||
| 	global commit_type commit_type_is_amend | ||||
| 	global commit_type selected_commit_type | ||||
| 
 | ||||
| 	if {$commit_type_is_amend == 0 | ||||
| 	if {$selected_commit_type eq {new} | ||||
| 		&& [string match amend* $commit_type]} { | ||||
| 		create_new_commit | ||||
| 	} elseif {$commit_type_is_amend == 1 | ||||
| 	} elseif {$selected_commit_type eq {amend} | ||||
| 		&& ![string match amend* $commit_type]} { | ||||
| 		load_last_commit | ||||
| 
 | ||||
| 		# The amend request was rejected... | ||||
| 		# | ||||
| 		if {![string match amend* $commit_type]} { | ||||
| 			set commit_type_is_amend 0 | ||||
| 			set selected_commit_type new | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
							
								
								
									
										14
									
								
								third_party/git/git-gui/lib/merge.tcl
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								third_party/git/git-gui/lib/merge.tcl
									
										
									
									
										vendored
									
									
								
							|  | @ -241,27 +241,23 @@ Continue with resetting the current changes?"] | |||
| 	if {[ask_popup $op_question] eq {yes}} { | ||||
| 		set fd [git_read --stderr read-tree --reset -u -v HEAD] | ||||
| 		fconfigure $fd -blocking 0 -translation binary | ||||
| 		set status_bar_operation [$::main_status \ | ||||
| 			start \ | ||||
| 			[mc "Aborting"] \ | ||||
| 			[mc "files reset"]] | ||||
| 		fileevent $fd readable [namespace code [list \ | ||||
| 			_reset_wait $fd $status_bar_operation]] | ||||
| 		fileevent $fd readable [namespace code [list _reset_wait $fd]] | ||||
| 		$::main_status start [mc "Aborting"] [mc "files reset"] | ||||
| 	} else { | ||||
| 		unlock_index | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| proc _reset_wait {fd status_bar_operation} { | ||||
| proc _reset_wait {fd} { | ||||
| 	global ui_comm | ||||
| 
 | ||||
| 	$status_bar_operation update_meter [read $fd] | ||||
| 	$::main_status update_meter [read $fd] | ||||
| 
 | ||||
| 	fconfigure $fd -blocking 1 | ||||
| 	if {[eof $fd]} { | ||||
| 		set fail [catch {close $fd} err] | ||||
| 		$::main_status stop | ||||
| 		unlock_index | ||||
| 		$status_bar_operation stop | ||||
| 
 | ||||
| 		$ui_comm delete 0.0 end | ||||
| 		$ui_comm edit modified false | ||||
|  |  | |||
							
								
								
									
										231
									
								
								third_party/git/git-gui/lib/status_bar.tcl
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										231
									
								
								third_party/git/git-gui/lib/status_bar.tcl
									
										
									
									
										vendored
									
									
								
							|  | @ -1,42 +1,16 @@ | |||
| # git-gui status bar mega-widget | ||||
| # Copyright (C) 2007 Shawn Pearce | ||||
| 
 | ||||
| # The status_bar class manages the entire status bar. It is possible for | ||||
| # multiple overlapping asynchronous operations to want to display status | ||||
| # simultaneously. Each one receives a status_bar_operation when it calls the | ||||
| # start method, and the status bar combines all active operations into the | ||||
| # line of text it displays. Most of the time, there will be at most one | ||||
| # ongoing operation. | ||||
| # | ||||
| # Note that the entire status bar can be either in single-line or two-line | ||||
| # mode, depending on the constructor. Multiple active operations are only | ||||
| # supported for single-line status bars. | ||||
| 
 | ||||
| class status_bar { | ||||
| 
 | ||||
| field allow_multiple ; # configured at construction | ||||
| 
 | ||||
| field w         ; # our own window path | ||||
| field w_l       ; # text widget we draw messages into | ||||
| field w_c       ; # canvas we draw a progress bar into | ||||
| field c_pack    ; # script to pack the canvas with | ||||
| 
 | ||||
| field baseline_text   ; # text to show if there are no operations | ||||
| field status_bar_text ; # combined text for all operations | ||||
| 
 | ||||
| field operations ; # list of current ongoing operations | ||||
| 
 | ||||
| # The status bar can display a progress bar, updated when consumers call the | ||||
| # update method on their status_bar_operation. When there are multiple | ||||
| # operations, the status bar shows the combined status of all operations. | ||||
| # | ||||
| # When an overlapping operation completes, the progress bar is going to | ||||
| # abruptly have one fewer operation in the calculation, causing a discontinuity. | ||||
| # Therefore, whenever an operation completes, if it is not the last operation, | ||||
| # this counter is increased, and the progress bar is calculated as though there | ||||
| # were still another operation at 100%. When the last operation completes, this | ||||
| # is reset to 0. | ||||
| field completed_operation_count | ||||
| field status  {}; # single line of text we show | ||||
| field prefix  {}; # text we format into status | ||||
| field units   {}; # unit of progress | ||||
| field meter   {}; # current core git progress meter (if active) | ||||
| 
 | ||||
| constructor new {path} { | ||||
| 	global use_ttk NS | ||||
|  | @ -44,19 +18,12 @@ constructor new {path} { | |||
| 	set w_l $w.l | ||||
| 	set w_c $w.c | ||||
| 
 | ||||
| 	# Standard single-line status bar: Permit overlapping operations | ||||
| 	set allow_multiple 1 | ||||
| 
 | ||||
| 	set baseline_text "" | ||||
| 	set operations [list] | ||||
| 	set completed_operation_count 0 | ||||
| 
 | ||||
| 	${NS}::frame $w | ||||
| 	if {!$use_ttk} { | ||||
| 		$w configure -borderwidth 1 -relief sunken | ||||
| 	} | ||||
| 	${NS}::label $w_l \ | ||||
| 		-textvariable @status_bar_text \ | ||||
| 		-textvariable @status \ | ||||
| 		-anchor w \ | ||||
| 		-justify left | ||||
| 	pack $w_l -side left | ||||
|  | @ -77,16 +44,9 @@ constructor two_line {path} { | |||
| 	set w_l $w.l | ||||
| 	set w_c $w.c | ||||
| 
 | ||||
| 	# Two-line status bar: Only one ongoing operation permitted. | ||||
| 	set allow_multiple 0 | ||||
| 
 | ||||
| 	set baseline_text "" | ||||
| 	set operations [list] | ||||
| 	set completed_operation_count 0 | ||||
| 
 | ||||
| 	${NS}::frame $w | ||||
| 	${NS}::label $w_l \ | ||||
| 		-textvariable @status_bar_text \ | ||||
| 		-textvariable @status \ | ||||
| 		-anchor w \ | ||||
| 		-justify left | ||||
| 	pack $w_l -anchor w -fill x | ||||
|  | @ -96,7 +56,7 @@ constructor two_line {path} { | |||
| 	return $this | ||||
| } | ||||
| 
 | ||||
| method ensure_canvas {} { | ||||
| method start {msg uds} { | ||||
| 	if {[winfo exists $w_c]} { | ||||
| 		$w_c coords bar 0 0 0 20 | ||||
| 	} else { | ||||
|  | @ -108,170 +68,31 @@ method ensure_canvas {} { | |||
| 		$w_c create rectangle 0 0 0 20 -tags bar -fill navy | ||||
| 		eval $c_pack | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| method show {msg} { | ||||
| 	$this ensure_canvas | ||||
| 	set baseline_text $msg | ||||
| 	$this refresh | ||||
| } | ||||
| 
 | ||||
| method start {msg {uds {}}} { | ||||
| 	set baseline_text "" | ||||
| 
 | ||||
| 	if {!$allow_multiple && [llength $operations]} { | ||||
| 		return [lindex $operations 0] | ||||
| 	} | ||||
| 
 | ||||
| 	$this ensure_canvas | ||||
| 
 | ||||
| 	set operation [status_bar_operation::new $this $msg $uds] | ||||
| 
 | ||||
| 	lappend operations $operation | ||||
| 
 | ||||
| 	$this refresh | ||||
| 
 | ||||
| 	return $operation | ||||
| } | ||||
| 
 | ||||
| method refresh {} { | ||||
| 	set new_text "" | ||||
| 
 | ||||
| 	set total [expr $completed_operation_count * 100] | ||||
| 	set have $total | ||||
| 
 | ||||
| 	foreach operation $operations { | ||||
| 		if {$new_text != ""} { | ||||
| 			append new_text " / " | ||||
| 		} | ||||
| 
 | ||||
| 		append new_text [$operation get_status] | ||||
| 
 | ||||
| 		set total [expr $total + 100] | ||||
| 		set have [expr $have + [$operation get_progress]] | ||||
| 	} | ||||
| 
 | ||||
| 	if {$new_text == ""} { | ||||
| 		set new_text $baseline_text | ||||
| 	} | ||||
| 
 | ||||
| 	set status_bar_text $new_text | ||||
| 
 | ||||
| 	if {[winfo exists $w_c]} { | ||||
| 		set pixel_width 0 | ||||
| 		if {$have > 0} { | ||||
| 			set pixel_width [expr {[winfo width $w_c] * $have / $total}] | ||||
| 		} | ||||
| 
 | ||||
| 		$w_c coords bar 0 0 $pixel_width 20 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| method stop {operation stop_msg} { | ||||
| 	set idx [lsearch $operations $operation] | ||||
| 
 | ||||
| 	if {$idx >= 0} { | ||||
| 		set operations [lreplace $operations $idx $idx] | ||||
| 		set completed_operation_count [expr \ | ||||
| 			$completed_operation_count + 1] | ||||
| 
 | ||||
| 		if {[llength $operations] == 0} { | ||||
| 			set completed_operation_count 0 | ||||
| 
 | ||||
| 			destroy $w_c | ||||
| 			if {$stop_msg ne {}} { | ||||
| 				set baseline_text $stop_msg | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		$this refresh | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| method stop_all {{stop_msg {}}} { | ||||
| 	# This makes the operation's call to stop a no-op. | ||||
| 	set operations_copy $operations | ||||
| 	set operations [list] | ||||
| 
 | ||||
| 	foreach operation $operations_copy { | ||||
| 		$operation stop | ||||
| 	} | ||||
| 
 | ||||
| 	if {$stop_msg ne {}} { | ||||
| 		set baseline_text $stop_msg | ||||
| 	} | ||||
| 
 | ||||
| 	$this refresh | ||||
| } | ||||
| 
 | ||||
| method _delete {current} { | ||||
| 	if {$current eq $w} { | ||||
| 		delete_this | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| # The status_bar_operation class tracks a single consumer's ongoing status bar | ||||
| # activity, with the context that there are a few situations where multiple | ||||
| # overlapping asynchronous operations might want to display status information | ||||
| # simultaneously. Instances of status_bar_operation are created by calling | ||||
| # start on the status_bar, and when the caller is done with its stauts bar | ||||
| # operation, it calls stop on the operation. | ||||
| 
 | ||||
| class status_bar_operation { | ||||
| 
 | ||||
| field status_bar; # reference back to the status_bar that owns this object | ||||
| 
 | ||||
| field is_active; | ||||
| 
 | ||||
| field status   {}; # single line of text we show | ||||
| field progress {}; # current progress (0 to 100) | ||||
| field prefix   {}; # text we format into status | ||||
| field units    {}; # unit of progress | ||||
| field meter    {}; # current core git progress meter (if active) | ||||
| 
 | ||||
| constructor new {owner msg uds} { | ||||
| 	set status_bar $owner | ||||
| 
 | ||||
| 	set status $msg | ||||
| 	set progress 0 | ||||
| 	set prefix $msg | ||||
| 	set units  $uds | ||||
| 	set meter  {} | ||||
| 
 | ||||
| 	set is_active 1 | ||||
| 
 | ||||
| 	return $this | ||||
| } | ||||
| 
 | ||||
| method get_is_active {} { return $is_active } | ||||
| method get_status {} { return $status } | ||||
| method get_progress {} { return $progress } | ||||
| 
 | ||||
| method update {have total} { | ||||
| 	if {!$is_active} { return } | ||||
| 
 | ||||
| 	set progress 0 | ||||
| 
 | ||||
| 	set pdone 0 | ||||
| 	set cdone 0 | ||||
| 	if {$total > 0} { | ||||
| 		set progress [expr {100 * $have / $total}] | ||||
| 		set pdone [expr {100 * $have / $total}] | ||||
| 		set cdone [expr {[winfo width $w_c] * $have / $total}] | ||||
| 	} | ||||
| 
 | ||||
| 	set prec [string length [format %i $total]] | ||||
| 
 | ||||
| 	set status [mc "%s ... %*i of %*i %s (%3i%%)" \ | ||||
| 		$prefix \ | ||||
| 		$prec $have \ | ||||
| 		$prec $total \ | ||||
| 		$units $progress] | ||||
| 
 | ||||
| 	$status_bar refresh | ||||
| 		$units $pdone] | ||||
| 	$w_c coords bar 0 0 $cdone 20 | ||||
| } | ||||
| 
 | ||||
| method update_meter {buf} { | ||||
| 	if {!$is_active} { return } | ||||
| 
 | ||||
| 	append meter $buf | ||||
| 	set r [string last "\r" $meter] | ||||
| 	if {$r == -1} { | ||||
|  | @ -288,25 +109,23 @@ method update_meter {buf} { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| method stop {{stop_msg {}}} { | ||||
| 	if {$is_active} { | ||||
| 		set is_active 0 | ||||
| 		$status_bar stop $this $stop_msg | ||||
| method stop {{msg {}}} { | ||||
| 	destroy $w_c | ||||
| 	if {$msg ne {}} { | ||||
| 		set status $msg | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| method restart {msg} { | ||||
| 	if {!$is_active} { return } | ||||
| 
 | ||||
| 	set status $msg | ||||
| 	set prefix $msg | ||||
| 	set meter {} | ||||
| 	$status_bar refresh | ||||
| method show {msg {test {}}} { | ||||
| 	if {$test eq {} || $status eq $test} { | ||||
| 		set status $msg | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| method _delete {} { | ||||
| 	stop | ||||
| 	delete_this | ||||
| method _delete {current} { | ||||
| 	if {$current eq $w} { | ||||
| 		delete_this | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue