Merge remote branch 'origin/hv/win-interactive-unlink' into work/1.7.0.2

This commit is contained in:
Johannes Schindelin
2010-03-08 16:14:41 +01:00
5 changed files with 142 additions and 0 deletions

View File

@@ -5,6 +5,7 @@
#include <shellapi.h>
#include "../strbuf.h"
#include "../cache.h"
#include "../run-command.h"
unsigned int _CRT_fmode = _O_BINARY;
static const int delay[] = { 0, 1, 10, 20, 40 };
@@ -158,6 +159,54 @@ int mingw_mkdir(const char *path, int mode)
return ret;
}
static int ask_user_yes_no(const char *format, ...)
{
char answer[5];
char question[4096];
const char *retry_hook[] = { NULL, NULL, NULL };
va_list args;
if ((retry_hook[0] = getenv("GIT_ASK_YESNO"))) {
va_start(args, format);
vsnprintf(question, sizeof(question), format, args);
va_end(args);
retry_hook[1] = question;
return !run_command_v_opt(retry_hook, 0);
}
if (!isatty(_fileno(stdin)))
return 0;
while (1) {
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
fprintf(stderr, " (y/n)? ");
if (fgets(answer, sizeof(answer), stdin)) {
/* remove the newline */
if (answer[strlen(answer)-2] == '\r')
answer[strlen(answer)-2] = '\0';
if (answer[strlen(answer)-1] == '\n')
answer[strlen(answer)-1] = '\0';
} else
return 0;
if (answer[0] == 'y' && strlen(answer) == 1)
return 1;
if (!strncasecmp(answer, "yes", sizeof(answer)))
return 1;
if (answer[0] == 'n' && strlen(answer) == 1)
return 0;
if (!strncasecmp(answer, "no", sizeof(answer)))
return 0;
fprintf(stderr, "I did not understand your answer: '%s'\n",
answer);
}
}
#undef unlink
int mingw_unlink(const char *pathname)
{
@@ -178,6 +227,35 @@ int mingw_unlink(const char *pathname)
Sleep(delay[tries]);
tries++;
}
while (ret == -1 && errno == EACCES &&
ask_user_yes_no("Unlink of file '%s' failed. "
"Should I try again?", pathname))
ret = unlink(pathname);
return ret;
}
#undef rmdir
int mingw_rmdir(const char *pathname)
{
int ret, tries = 0;
while ((ret = rmdir(pathname)) == -1 && tries < ARRAY_SIZE(delay)) {
if (errno != EACCES)
break;
/*
* We assume that some other process had the source or
* destination file open at the wrong moment and retry.
* In order to give the other process a higher chance to
* complete its operation, we give up our time slice now.
* If we have to retry again, we do sleep a bit.
*/
Sleep(delay[tries]);
tries++;
}
while (ret == -1 && errno == EACCES &&
ask_user_yes_no("Deletion of directory '%s' failed. "
"Should I try again?", pathname))
ret = rmdir(pathname);
return ret;
}
@@ -1277,6 +1355,11 @@ repeat:
tries++;
goto repeat;
}
if (gle == ERROR_ACCESS_DENIED &&
ask_user_yes_no("Rename from '%s' to '%s' failed. "
"Should I try again?", pold, pnew))
goto repeat;
errno = EACCES;
return -1;
}

View File

@@ -170,6 +170,9 @@ int mingw_mkdir(const char *path, int mode);
int mingw_unlink(const char *pathname);
#define unlink mingw_unlink
int mingw_rmdir(const char *path);
#define rmdir mingw_rmdir
int mingw_open (const char *filename, int oflags, ...);
#define open mingw_open

View File

@@ -289,6 +289,7 @@ install: all
$(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(INSTALL_D1)
$(QUIET)$(INSTALL_X0)git-gui $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
$(QUIET)$(INSTALL_X0)git-gui--askpass $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
$(QUIET)$(INSTALL_X0)git-gui--askyesno $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
$(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(INSTALL_L0)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L1)'$(DESTDIR_SQ)$(gitexecdir_SQ)/git-gui' $(INSTALL_L2)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L3) &&) true
ifdef GITGUI_WINDOWS_WRAPPER
$(QUIET)$(INSTALL_R0)git-gui.tcl $(INSTALL_R1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
@@ -307,6 +308,7 @@ uninstall:
$(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui $(REMOVE_F1)
$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui--askpass $(REMOVE_F1)
$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui--askyesno $(REMOVE_F1)
$(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/$p $(REMOVE_F1) &&) true
ifdef GITGUI_WINDOWS_WRAPPER
$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui.tcl $(REMOVE_F1)

51
git-gui/git-gui--askyesno Executable file
View File

@@ -0,0 +1,51 @@
#!/bin/sh
# Tcl ignores the next line -*- tcl -*- \
exec wish "$0" -- "$@"
# This is an implementation of a simple yes no dialog
# which is injected into the git commandline by git gui
# in case a yesno question needs to be answered.
set NS {}
set use_ttk [package vsatisfies [package provide Tk] 8.5]
if {$use_ttk} {
set NS ttk
}
if {$argc < 1} {
puts stderr "Usage: $argv0 <question>"
exit 1
} else {
set prompt [join $argv " "]
}
${NS}::frame .t
${NS}::label .t.m -text $prompt -justify center -width 40
.t.m configure -wraplength 400
pack .t.m -side top -fill x -padx 20 -pady 20 -expand 1
pack .t -side top -fill x -ipadx 20 -ipady 20 -expand 1
${NS}::frame .b
${NS}::frame .b.left -width 200
${NS}::button .b.yes -text Yes -command yes
${NS}::button .b.no -text No -command no
pack .b.left -side left -expand 1 -fill x
pack .b.yes -side left -expand 1
pack .b.no -side right -expand 1 -ipadx 5
pack .b -side bottom -fill x -ipadx 20 -ipady 15
bind . <Key-Return> {exit 0}
bind . <Key-Escape> {exit 1}
proc no {} {
exit 1
}
proc yes {} {
exit 0
}
wm title . "Question?"
tk::PlaceWindow .

View File

@@ -1115,6 +1115,9 @@ set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
if {![info exists env(SSH_ASKPASS)]} {
set env(SSH_ASKPASS) [gitexec git-gui--askpass]
}
if {![info exists env(GIT_ASK_YESNO)]} {
set env(GIT_ASK_YESNO) [gitexec git-gui--askyesno]
}
######################################################################
##