From 337967fb7794b300f1633a413c0db525ab517a3e Mon Sep 17 00:00:00 2001 From: Heiko Voigt Date: Mon, 7 Feb 2011 21:49:33 +0100 Subject: mingw: move unlink wrapper to mingw.c The next patch implements a workaround in case unlink fails on Windows. Signed-off-by: Heiko Voigt Signed-off-by: Junio C Hamano --- compat/mingw.c | 8 ++++++++ compat/mingw.h | 11 +++-------- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'compat') diff --git a/compat/mingw.c b/compat/mingw.c index bee6054419..a7e1c6b471 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -116,6 +116,14 @@ int err_win_to_posix(DWORD winerr) return error; } +#undef unlink +int mingw_unlink(const char *pathname) +{ + /* read-only files cannot be removed */ + chmod(pathname, 0666); + return unlink(pathname); +} + #undef open int mingw_open (const char *filename, int oflags, ...) { diff --git a/compat/mingw.h b/compat/mingw.h index 2283071109..8316938020 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -125,14 +125,6 @@ static inline int mingw_mkdir(const char *path, int mode) } #define mkdir mingw_mkdir -static inline int mingw_unlink(const char *pathname) -{ - /* read-only files cannot be removed */ - chmod(pathname, 0666); - return unlink(pathname); -} -#define unlink mingw_unlink - #define WNOHANG 1 pid_t waitpid(pid_t pid, int *status, unsigned options); @@ -180,6 +172,9 @@ int link(const char *oldpath, const char *newpath); * replacements of existing functions */ +int mingw_unlink(const char *pathname); +#define unlink mingw_unlink + int mingw_open (const char *filename, int oflags, ...); #define open mingw_open -- cgit v1.3 From 19e125498bc417e20f0b8c1014b808654e4acfe4 Mon Sep 17 00:00:00 2001 From: Heiko Voigt Date: Mon, 7 Feb 2011 21:50:26 +0100 Subject: mingw: work around irregular failures of unlink on windows If a file is opened by another process (e.g. indexing of an IDE) for reading it is not allowed to be deleted. So in case unlink fails retry after waiting for some time. This extends the workaround from 6ac6f878. Signed-off-by: Heiko Voigt Signed-off-by: Junio C Hamano --- compat/mingw.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'compat') diff --git a/compat/mingw.c b/compat/mingw.c index a7e1c6b471..9421a37c19 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -3,6 +3,8 @@ #include #include "../strbuf.h" +static const int delay[] = { 0, 1, 10, 20, 40 }; + int err_win_to_posix(DWORD winerr) { int error = ENOSYS; @@ -116,12 +118,38 @@ int err_win_to_posix(DWORD winerr) return error; } +static inline int is_file_in_use_error(DWORD errcode) +{ + switch (errcode) { + case ERROR_SHARING_VIOLATION: + case ERROR_ACCESS_DENIED: + return 1; + } + + return 0; +} + #undef unlink int mingw_unlink(const char *pathname) { + int ret, tries = 0; + /* read-only files cannot be removed */ chmod(pathname, 0666); - return unlink(pathname); + while ((ret = unlink(pathname)) == -1 && tries < ARRAY_SIZE(delay)) { + if (!is_file_in_use_error(GetLastError())) + 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++; + } + return ret; } #undef open @@ -1257,7 +1285,6 @@ int mingw_rename(const char *pold, const char *pnew) { DWORD attrs, gle; int tries = 0; - static const int delay[] = { 0, 1, 10, 20, 40 }; /* * Try native rename() first to get errno right. -- cgit v1.3 From c9b78400802acb3e02249c44286162edd9ed2b35 Mon Sep 17 00:00:00 2001 From: Heiko Voigt Date: Mon, 7 Feb 2011 21:51:21 +0100 Subject: mingw: make failures to unlink or move raise a question On Windows in case a program is accessing a file unlink or move operations may fail. To give the user a chance to correct this we simply wait until the user asks us to retry or fail. This is useful because of the following use case which seem to happen rarely but when it does it is a mess: After making some changes the user realizes that he was on the incorrect branch. When trying to change the branch some file is still in use by some other process and git stops in the middle of changing branches. Now the user has lots of files with changes mixed with his own. This is especially confusing on repositories that contain lots of files. Although the recent implementation of automatic retry makes this scenario much more unlikely lets provide a fallback as a last resort. Thanks to Albert Dvornik for disabling the question if users can't see it. If the stdout of the command is connected to a terminal but the stderr has been redirected, the odds are good that the user can't see any question we print out to stderr. This will result in a "mysterious hang" while the app is waiting for user input. It seems better to be conservative, and avoid asking for input whenever the stderr is not a terminal, just like we do for stdin. Signed-off-by: Heiko Voigt Signed-off-by: Albert Dvornik Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- compat/mingw.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) (limited to 'compat') diff --git a/compat/mingw.c b/compat/mingw.c index 9421a37c19..e8e20282df 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2,6 +2,7 @@ #include "win32.h" #include #include "../strbuf.h" +#include "../run-command.h" static const int delay[] = { 0, 1, 10, 20, 40 }; @@ -129,6 +130,74 @@ static inline int is_file_in_use_error(DWORD errcode) return 0; } +static int read_yes_no_answer(void) +{ + char answer[1024]; + + if (fgets(answer, sizeof(answer), stdin)) { + size_t answer_len = strlen(answer); + int got_full_line = 0, c; + + /* remove the newline */ + if (answer_len >= 2 && answer[answer_len-2] == '\r') { + answer[answer_len-2] = '\0'; + got_full_line = 1; + } else if (answer_len >= 1 && answer[answer_len-1] == '\n') { + answer[answer_len-1] = '\0'; + got_full_line = 1; + } + /* flush the buffer in case we did not get the full line */ + if (!got_full_line) + while ((c = getchar()) != EOF && c != '\n') + ; + } else + /* we could not read, return the + * default answer which is no */ + return 0; + + if (tolower(answer[0]) == 'y' && !answer[1]) + return 1; + if (!strncasecmp(answer, "yes", sizeof(answer))) + return 1; + if (tolower(answer[0]) == 'n' && !answer[1]) + return 0; + if (!strncasecmp(answer, "no", sizeof(answer))) + return 0; + + /* did not find an answer we understand */ + return -1; +} + +static int ask_yes_no_if_possible(const char *format, ...) +{ + char question[4096]; + const char *retry_hook[] = { NULL, NULL, NULL }; + va_list args; + + va_start(args, format); + vsnprintf(question, sizeof(question), format, args); + va_end(args); + + if ((retry_hook[0] = getenv("GIT_ASK_YESNO"))) { + retry_hook[1] = question; + return !run_command_v_opt(retry_hook, 0); + } + + if (!isatty(_fileno(stdin)) || !isatty(_fileno(stderr))) + return 0; + + while (1) { + int answer; + fprintf(stderr, "%s (y/n) ", question); + + if ((answer = read_yes_no_answer()) >= 0) + return answer; + + fprintf(stderr, "Sorry, I did not understand your answer. " + "Please type 'y' or 'n'\n"); + } +} + #undef unlink int mingw_unlink(const char *pathname) { @@ -149,6 +218,10 @@ int mingw_unlink(const char *pathname) Sleep(delay[tries]); tries++; } + while (ret == -1 && is_file_in_use_error(GetLastError()) && + ask_yes_no_if_possible("Unlink of file '%s' failed. " + "Should I try again?", pathname)) + ret = unlink(pathname); return ret; } @@ -1326,6 +1399,11 @@ repeat: tries++; goto repeat; } + if (gle == ERROR_ACCESS_DENIED && + ask_yes_no_if_possible("Rename from '%s' to '%s' failed. " + "Should I try again?", pold, pnew)) + goto repeat; + errno = EACCES; return -1; } -- cgit v1.3 From 4f288100ceed14c65a1e964b2db4aaee4f4199fc Mon Sep 17 00:00:00 2001 From: Heiko Voigt Date: Mon, 7 Feb 2011 21:52:34 +0100 Subject: mingw: add fallback for rmdir in case directory is in use The same logic as for unlink and rename also applies to rmdir. For example in case you have a shell open in a git controlled folder. This will easily fail. So lets be nice for such cases as well. Signed-off-by: Heiko Voigt Signed-off-by: Junio C Hamano --- compat/mingw.c | 25 +++++++++++++++++++++++++ compat/mingw.h | 3 +++ 2 files changed, 28 insertions(+) (limited to 'compat') diff --git a/compat/mingw.c b/compat/mingw.c index e8e20282df..e55c3cac77 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -225,6 +225,31 @@ int mingw_unlink(const char *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 (!is_file_in_use_error(GetLastError())) + 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 && is_file_in_use_error(GetLastError()) && + ask_yes_no_if_possible("Deletion of directory '%s' failed. " + "Should I try again?", pathname)) + ret = rmdir(pathname); + return ret; +} + #undef open int mingw_open (const char *filename, int oflags, ...) { diff --git a/compat/mingw.h b/compat/mingw.h index 8316938020..8b159c4447 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -175,6 +175,9 @@ int link(const char *oldpath, const char *newpath); 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 -- cgit v1.3 From ab1a11be7858e1f92ee2e4ee1d70fabe7d5fe0ee Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 7 Feb 2011 21:54:01 +0100 Subject: mingw_rmdir: set errno=ENOTEMPTY when appropriate On Windows, EACCES overrules ENOTEMPTY when calling rmdir(). But if the directory is busy, we only want to retry deleting the directory if it is empty, so test specifically for that case and set ENOTEMPTY rather than EACCES. Noticed by Greg Hazel. Signed-off-by: Johannes Schindelin Signed-off-by: Heiko Voigt Signed-off-by: Junio C Hamano --- compat/mingw.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'compat') diff --git a/compat/mingw.c b/compat/mingw.c index e55c3cac77..878b1de97c 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -225,6 +225,30 @@ int mingw_unlink(const char *pathname) return ret; } +static int is_dir_empty(const char *path) +{ + struct strbuf buf = STRBUF_INIT; + WIN32_FIND_DATAA findbuf; + HANDLE handle; + + strbuf_addf(&buf, "%s\\*", path); + handle = FindFirstFileA(buf.buf, &findbuf); + if (handle == INVALID_HANDLE_VALUE) { + strbuf_release(&buf); + return GetLastError() == ERROR_NO_MORE_FILES; + } + + while (!strcmp(findbuf.cFileName, ".") || + !strcmp(findbuf.cFileName, "..")) + if (!FindNextFile(handle, &findbuf)) { + strbuf_release(&buf); + return GetLastError() == ERROR_NO_MORE_FILES; + } + FindClose(handle); + strbuf_release(&buf); + return 0; +} + #undef rmdir int mingw_rmdir(const char *pathname) { @@ -233,6 +257,10 @@ int mingw_rmdir(const char *pathname) while ((ret = rmdir(pathname)) == -1 && tries < ARRAY_SIZE(delay)) { if (!is_file_in_use_error(GetLastError())) break; + if (!is_dir_empty(pathname)) { + errno = ENOTEMPTY; + break; + } /* * We assume that some other process had the source or * destination file open at the wrong moment and retry. -- cgit v1.3 From ab8632ae36d2e5faf524309696725b60ec18e588 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Fri, 25 Feb 2011 23:08:25 -0600 Subject: compat: provide a fallback va_copy definition va_copy is C99. We have avoided using va_copy many times in the past, which has led to a bunch of cut-and-paste. From everything I found searching the web, implementations have historically either provided va_copy or just let your code assume that simple assignment of worked. So my guess is that this will be sufficient, though we won't really know for sure until somebody reports a problem. Signed-off-by: Jeff King Improved-by: Erik Faye-Lund Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- compat/msvc.h | 1 - git-compat-util.h | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'compat') diff --git a/compat/msvc.h b/compat/msvc.h index 023aba0238..a33b01c032 100644 --- a/compat/msvc.h +++ b/compat/msvc.h @@ -9,7 +9,6 @@ #define inline __inline #define __inline__ __inline #define __attribute__(x) -#define va_copy(dst, src) ((dst) = (src)) #define strncasecmp _strnicmp #define ftruncate _chsize diff --git a/git-compat-util.h b/git-compat-util.h index 9c23622ed5..00d41e4f0e 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -535,6 +535,10 @@ void git_qsort(void *base, size_t nmemb, size_t size, #define fstat_is_reliable() 1 #endif +#ifndef va_copy +#define va_copy(dst,src) (dst) = (src) +#endif + /* * Preserves errno, prints a message, but gives no warning for ENOENT. * Always returns the return value of unlink(2). -- cgit v1.3 From 0353a0c4ec91cf2d0a8e209025aa2e1909d05f19 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Wed, 13 Apr 2011 17:39:40 +0200 Subject: remove doubled words, e.g., s/to to/to/, and fix related typos I found that some doubled words had snuck back into projects from which I'd already removed them, so now there's a "syntax-check" makefile rule in gnulib to help prevent recurrence. Running the command below spotted a few in git, too: git ls-files | xargs perl -0777 -n \ -e 'while (/\b(then?|[iao]n|i[fst]|but|f?or|at|and|[dt])\s+\1\b/gims)' \ -e '{$n=($` =~ tr/\n/\n/ + 1); ($v=$&)=~s/\n/\\n/g;' \ -e 'print "$ARGV:$n:$v\n"}' Signed-off-by: Jim Meyering Signed-off-by: Junio C Hamano --- Documentation/SubmittingPatches | 3 +-- Documentation/git-fetch.txt | 2 +- Documentation/git-pack-objects.txt | 2 +- compat/mingw.c | 2 +- compat/nedmalloc/malloc.c.h | 10 ++++------ gitweb/README | 2 +- sha1_file.c | 2 +- vcs-svn/trp.txt | 2 +- 8 files changed, 11 insertions(+), 14 deletions(-) (limited to 'compat') diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index c3b0816ed7..c6a5032912 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -276,7 +276,7 @@ don't hide your real name. If you like, you can put extra tags at the end: -1. "Reported-by:" is used to to credit someone who found the bug that +1. "Reported-by:" is used to credit someone who found the bug that the patch attempts to fix. 2. "Acked-by:" says that the person who is more familiar with the area the patch attempts to modify liked the patch. @@ -608,4 +608,3 @@ following commands: Just make sure to disable line wrapping in the email client (GMail web interface will line wrap no matter what, so you need to use a real IMAP client). - diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt index 67d221467d..60ac8d26eb 100644 --- a/Documentation/git-fetch.txt +++ b/Documentation/git-fetch.txt @@ -34,7 +34,7 @@ pointed by remote tags that it does not yet have, then fetch those missing tags. If the other end has tags that point at branches you are not interested in, you will not get them. -'git fetch' can fetch from either a single named repository, or +'git fetch' can fetch from either a single named repository, or from several repositories at once if is given and there is a remotes. entry in the configuration file. (See linkgit:git-config[1]). diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index 08c89d221c..20c8551d6a 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -115,7 +115,7 @@ base-name:: --honor-pack-keep:: This flag causes an object already in a local pack that - has a .keep file to be ignored, even if it it would have + has a .keep file to be ignored, even if it would have otherwise been packed. --incremental:: diff --git a/compat/mingw.c b/compat/mingw.c index 878b1de97c..4423961768 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -1130,7 +1130,7 @@ char **make_augmented_environ(const char *const *vars) /* * Note, this isn't a complete replacement for getaddrinfo. It assumes - * that service contains a numerical port, or that it it is null. It + * that service contains a numerical port, or that it is null. It * does a simple search using gethostbyname, and returns one IPv4 host * if one was found. */ diff --git a/compat/nedmalloc/malloc.c.h b/compat/nedmalloc/malloc.c.h index 87260d2642..ff7c2c4fd8 100644 --- a/compat/nedmalloc/malloc.c.h +++ b/compat/nedmalloc/malloc.c.h @@ -100,7 +100,7 @@ If you don't like either of these options, you can define CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything - else. And if if you are sure that your program using malloc has + else. And if you are sure that your program using malloc has no errors or vulnerabilities, you can define INSECURE to 1, which might (or might not) provide a small performance improvement. @@ -2279,12 +2279,12 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ of the same size are arranged in a circularly-linked list, with only the oldest chunk (the next to be used, in our FIFO ordering) actually in the tree. (Tree members are distinguished by a non-null - parent pointer.) If a chunk with the same size an an existing node + parent pointer.) If a chunk with the same size as an existing node is inserted, it is linked off the existing node using pointers that work in the same way as fd/bk pointers of small chunks. Each tree contains a power of 2 sized range of chunk sizes (the - smallest is 0x100 <= x < 0x180), which is is divided in half at each + smallest is 0x100 <= x < 0x180), which is divided in half at each tree level, with the chunks in the smaller half of the range (0x100 <= x < 0x140 for the top nose) in the left subtree and the larger half (0x140 <= x < 0x180) in the right subtree. This is, of course, @@ -3943,7 +3943,7 @@ static void* sys_alloc(mstate m, size_t nb) { least-preferred order): 1. A call to MORECORE that can normally contiguously extend memory. (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or - or main space is mmapped or a previous contiguous call failed) + main space is mmapped or a previous contiguous call failed) 2. A call to MMAP new space (disabled if not HAVE_MMAP). Note that under the default settings, if MORECORE is unable to fulfill a request, and HAVE_MMAP is true, then mmap is @@ -5748,5 +5748,3 @@ History: structure of old version, but most details differ.) */ - - diff --git a/gitweb/README b/gitweb/README index 4a673933ac..a92bde7f14 100644 --- a/gitweb/README +++ b/gitweb/README @@ -29,7 +29,7 @@ You can specify the following configuration variables when building GIT: The filesystem traversing limit for getting the project list; the number is taken as depth relative to the projectroot. It is used when GITWEB_LIST is a directory (or is not set; then project root is used). - Is is meant to speed up project listing on large work trees by limiting + This is meant to speed up project listing on large work trees by limiting search depth. [Default: 2007] * GITWEB_LIST Points to a directory to scan for projects (defaults to project root diff --git a/sha1_file.c b/sha1_file.c index df0edbad1e..889fe71830 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1534,7 +1534,7 @@ static int unpack_object_header(struct packed_git *p, enum object_type type; /* use_pack() assures us we have [base, base + 20) available - * as a range that we can look at at. (Its actually the hash + * as a range that we can look at. (Its actually the hash * size that is assured.) With our object header encoding * the maximum deflated object size is 2^137, which is just * insane, so we know won't exceed what we have been given. diff --git a/vcs-svn/trp.txt b/vcs-svn/trp.txt index 5ca6b42edb..177ebca335 100644 --- a/vcs-svn/trp.txt +++ b/vcs-svn/trp.txt @@ -96,7 +96,7 @@ node_type *foo_search(struct trp_root \*treap, node_type \*key):: node_type *foo_nsearch(struct trp_root \*treap, node_type \*key):: - Like `foo_search`, but if if the key is missing return what + Like `foo_search`, but if the key is missing return what would be key's successor, were key in treap (NULL if no successor). -- cgit v1.3