Add new "git replace" command
[gitweb.git] / compat / mingw.c
index 2839d9df6ee8ed1e7227769877b04dd9b542f496..e190fddf41d6b15d9254859fca8b638ed7c0f428 100644 (file)
@@ -396,7 +396,7 @@ int poll(struct pollfd *ufds, unsigned int nfds, int timeout)
                 * its own input data to become available. But since
                 * the process (pack-objects) is itself CPU intensive,
                 * it will happily pick up the time slice that we are
-                * relinguishing here.
+                * relinquishing here.
                 */
                Sleep(0);
                goto repeat;
@@ -525,8 +525,8 @@ static const char *parse_interpreter(const char *cmd)
        if (buf[0] != '#' || buf[1] != '!')
                return NULL;
        buf[n] = '\0';
-       p = strchr(buf, '\n');
-       if (!p)
+       p = buf + strcspn(buf, "\r\n");
+       if (!*p)
                return NULL;
 
        *p = '\0';
@@ -562,7 +562,7 @@ static char **get_path_split(void)
        if (!n)
                return NULL;
 
-       path = xmalloc((n+1)*sizeof(char*));
+       path = xmalloc((n+1)*sizeof(char *));
        p = envpath;
        i = 0;
        do {
@@ -934,7 +934,9 @@ int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)
 #undef rename
 int mingw_rename(const char *pold, const char *pnew)
 {
-       DWORD attrs;
+       DWORD attrs, gle;
+       int tries = 0;
+       static const int delay[] = { 0, 1, 10, 20, 40 };
 
        /*
         * Try native rename() first to get errno right.
@@ -944,10 +946,12 @@ int mingw_rename(const char *pold, const char *pnew)
                return 0;
        if (errno != EEXIST)
                return -1;
+repeat:
        if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
                return 0;
        /* TODO: translate more errors */
-       if (GetLastError() == ERROR_ACCESS_DENIED &&
+       gle = GetLastError();
+       if (gle == ERROR_ACCESS_DENIED &&
            (attrs = GetFileAttributes(pnew)) != INVALID_FILE_ATTRIBUTES) {
                if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
                        errno = EISDIR;
@@ -957,10 +961,23 @@ int mingw_rename(const char *pold, const char *pnew)
                    SetFileAttributes(pnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {
                        if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
                                return 0;
+                       gle = GetLastError();
                        /* revert file attributes on failure */
                        SetFileAttributes(pnew, attrs);
                }
        }
+       if (tries < ARRAY_SIZE(delay) && gle == ERROR_ACCESS_DENIED) {
+               /*
+                * 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++;
+               goto repeat;
+       }
        errno = EACCES;
        return -1;
 }
@@ -1139,3 +1156,18 @@ int link(const char *oldpath, const char *newpath)
        }
        return 0;
 }
+
+char *getpass(const char *prompt)
+{
+       struct strbuf buf = STRBUF_INIT;
+
+       fputs(prompt, stderr);
+       for (;;) {
+               char c = _getch();
+               if (c == '\r' || c == '\n')
+                       break;
+               strbuf_addch(&buf, c);
+       }
+       fputs("\n", stderr);
+       return strbuf_detach(&buf, NULL);
+}