rugged 0.26.0b5 → 0.26.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/rugged.c +24 -0
  3. data/ext/rugged/rugged.h +2 -0
  4. data/ext/rugged/rugged_signature.c +15 -2
  5. data/lib/rugged/version.rb +1 -1
  6. data/vendor/libgit2/CMakeLists.txt +9 -8
  7. data/vendor/libgit2/include/git2/common.h +29 -0
  8. data/vendor/libgit2/include/git2/errors.h +2 -0
  9. data/vendor/libgit2/include/git2/global.h +1 -1
  10. data/vendor/libgit2/include/git2/odb.h +2 -2
  11. data/vendor/libgit2/include/git2/odb_backend.h +1 -1
  12. data/vendor/libgit2/include/git2/remote.h +3 -3
  13. data/vendor/libgit2/include/git2/repository.h +2 -2
  14. data/vendor/libgit2/include/git2/sys/filter.h +11 -0
  15. data/vendor/libgit2/include/git2/sys/merge.h +5 -5
  16. data/vendor/libgit2/include/git2/sys/transport.h +10 -0
  17. data/vendor/libgit2/include/git2/transport.h +6 -6
  18. data/vendor/libgit2/include/git2/version.h +3 -3
  19. data/vendor/libgit2/include/git2/worktree.h +69 -10
  20. data/vendor/libgit2/libgit2.pc.in +2 -2
  21. data/vendor/libgit2/src/attr_file.c +6 -2
  22. data/vendor/libgit2/src/attrcache.c +7 -5
  23. data/vendor/libgit2/src/blame_git.c +12 -8
  24. data/vendor/libgit2/src/branch.c +17 -48
  25. data/vendor/libgit2/src/buffer.c +11 -12
  26. data/vendor/libgit2/src/buffer.h +2 -2
  27. data/vendor/libgit2/src/checkout.c +3 -6
  28. data/vendor/libgit2/src/config.c +42 -35
  29. data/vendor/libgit2/src/config_cache.c +1 -0
  30. data/vendor/libgit2/src/config_file.c +19 -11
  31. data/vendor/libgit2/src/config_file.h +1 -0
  32. data/vendor/libgit2/src/diff.c +35 -0
  33. data/vendor/libgit2/src/diff_parse.c +7 -1
  34. data/vendor/libgit2/src/filebuf.c +12 -1
  35. data/vendor/libgit2/src/filebuf.h +3 -1
  36. data/vendor/libgit2/src/fileops.c +83 -22
  37. data/vendor/libgit2/src/fileops.h +25 -0
  38. data/vendor/libgit2/src/filter.c +30 -14
  39. data/vendor/libgit2/src/global.c +1 -1
  40. data/vendor/libgit2/src/hash/hash_collisiondetect.h +1 -11
  41. data/vendor/libgit2/src/hash/sha1dc/sha1.c +894 -187
  42. data/vendor/libgit2/src/hash/sha1dc/sha1.h +69 -53
  43. data/vendor/libgit2/src/hash/sha1dc/ubc_check.c +13 -2
  44. data/vendor/libgit2/src/hash/sha1dc/ubc_check.h +20 -3
  45. data/vendor/libgit2/src/idxmap.c +1 -1
  46. data/vendor/libgit2/src/idxmap.h +1 -2
  47. data/vendor/libgit2/src/index.c +75 -42
  48. data/vendor/libgit2/src/indexer.c +31 -11
  49. data/vendor/libgit2/src/indexer.h +12 -0
  50. data/vendor/libgit2/src/merge.c +20 -0
  51. data/vendor/libgit2/src/merge_driver.c +29 -0
  52. data/vendor/libgit2/src/odb.c +96 -19
  53. data/vendor/libgit2/src/odb.h +25 -0
  54. data/vendor/libgit2/src/odb_loose.c +20 -6
  55. data/vendor/libgit2/src/odb_pack.c +1 -1
  56. data/vendor/libgit2/src/offmap.c +1 -1
  57. data/vendor/libgit2/src/offmap.h +1 -2
  58. data/vendor/libgit2/src/oidmap.c +1 -1
  59. data/vendor/libgit2/src/oidmap.h +1 -2
  60. data/vendor/libgit2/src/openssl_stream.c +11 -4
  61. data/vendor/libgit2/src/pack-objects.c +4 -0
  62. data/vendor/libgit2/src/pack-objects.h +1 -0
  63. data/vendor/libgit2/src/pack.c +5 -3
  64. data/vendor/libgit2/src/patch_generate.c +8 -79
  65. data/vendor/libgit2/src/patch_parse.c +5 -4
  66. data/vendor/libgit2/src/path.c +9 -7
  67. data/vendor/libgit2/src/posix.c +2 -0
  68. data/vendor/libgit2/src/posix.h +10 -0
  69. data/vendor/libgit2/src/rebase.c +12 -10
  70. data/vendor/libgit2/src/refdb_fs.c +33 -10
  71. data/vendor/libgit2/src/refs.c +89 -8
  72. data/vendor/libgit2/src/refs.h +14 -0
  73. data/vendor/libgit2/src/remote.c +9 -10
  74. data/vendor/libgit2/src/repository.c +178 -146
  75. data/vendor/libgit2/src/repository.h +25 -0
  76. data/vendor/libgit2/src/revparse.c +22 -3
  77. data/vendor/libgit2/src/revwalk.c +6 -3
  78. data/vendor/libgit2/src/settings.c +22 -1
  79. data/vendor/libgit2/src/signature.c +4 -1
  80. data/vendor/libgit2/src/socket_stream.c +2 -4
  81. data/vendor/libgit2/src/strmap.c +1 -1
  82. data/vendor/libgit2/src/strmap.h +1 -3
  83. data/vendor/libgit2/src/submodule.c +27 -7
  84. data/vendor/libgit2/src/sysdir.c +11 -0
  85. data/vendor/libgit2/src/sysdir.h +12 -0
  86. data/vendor/libgit2/src/transports/http.c +3 -0
  87. data/vendor/libgit2/src/transports/smart.c +6 -0
  88. data/vendor/libgit2/src/transports/smart_protocol.c +2 -1
  89. data/vendor/libgit2/src/transports/ssh.c +13 -1
  90. data/vendor/libgit2/src/transports/winhttp.c +1 -2
  91. data/vendor/libgit2/src/tree.c +13 -11
  92. data/vendor/libgit2/src/unix/posix.h +6 -1
  93. data/vendor/libgit2/src/varint.c +1 -1
  94. data/vendor/libgit2/src/win32/posix.h +3 -0
  95. data/vendor/libgit2/src/win32/posix_w32.c +334 -111
  96. data/vendor/libgit2/src/worktree.c +174 -48
  97. data/vendor/libgit2/src/worktree.h +1 -1
  98. metadata +77 -76
@@ -36,7 +36,7 @@ int git_encode_varint(unsigned char *buf, size_t bufsize, uintmax_t value)
36
36
  while (value >>= 7)
37
37
  varint[--pos] = 128 | (--value & 127);
38
38
  if (buf) {
39
- if (bufsize < pos)
39
+ if (bufsize < (sizeof(varint) - pos))
40
40
  return -1;
41
41
  memcpy(buf, varint + pos, sizeof(varint) - pos);
42
42
  }
@@ -14,6 +14,9 @@
14
14
  #include "utf-conv.h"
15
15
  #include "dir.h"
16
16
 
17
+ extern unsigned long git_win32__createfile_sharemode;
18
+ extern int git_win32__retries;
19
+
17
20
  typedef SOCKET GIT_SOCKET;
18
21
 
19
22
  #define p_lseek(f,n,w) _lseeki64(f, n, w)
@@ -26,15 +26,6 @@
26
26
  #define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
27
27
  #endif
28
28
 
29
- /* Options which we always provide to _wopen.
30
- *
31
- * _O_BINARY - Raw access; no translation of CR or LF characters
32
- * _O_NOINHERIT - Do not mark the created handle as inheritable by child processes.
33
- * The Windows default is 'not inheritable', but the CRT's default (following
34
- * POSIX convention) is 'inheritable'. We have no desire for our handles to be
35
- * inheritable on Windows, so specify the flag to get default behavior back. */
36
- #define STANDARD_OPEN_FLAGS (_O_BINARY | _O_NOINHERIT)
37
-
38
29
  /* Allowable mode bits on Win32. Using mode bits that are not supported on
39
30
  * Win32 (eg S_IRWXU) is generally ignored, but Wine warns loudly about it
40
31
  * so we simply remove them.
@@ -44,6 +35,164 @@
44
35
  /* GetFinalPathNameByHandleW signature */
45
36
  typedef DWORD(WINAPI *PFGetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, DWORD);
46
37
 
38
+ unsigned long git_win32__createfile_sharemode =
39
+ FILE_SHARE_READ | FILE_SHARE_WRITE;
40
+ int git_win32__retries = 10;
41
+
42
+ GIT_INLINE(void) set_errno(void)
43
+ {
44
+ switch (GetLastError()) {
45
+ case ERROR_FILE_NOT_FOUND:
46
+ case ERROR_PATH_NOT_FOUND:
47
+ case ERROR_INVALID_DRIVE:
48
+ case ERROR_NO_MORE_FILES:
49
+ case ERROR_BAD_NETPATH:
50
+ case ERROR_BAD_NET_NAME:
51
+ case ERROR_BAD_PATHNAME:
52
+ case ERROR_FILENAME_EXCED_RANGE:
53
+ errno = ENOENT;
54
+ break;
55
+ case ERROR_BAD_ENVIRONMENT:
56
+ errno = E2BIG;
57
+ break;
58
+ case ERROR_BAD_FORMAT:
59
+ case ERROR_INVALID_STARTING_CODESEG:
60
+ case ERROR_INVALID_STACKSEG:
61
+ case ERROR_INVALID_MODULETYPE:
62
+ case ERROR_INVALID_EXE_SIGNATURE:
63
+ case ERROR_EXE_MARKED_INVALID:
64
+ case ERROR_BAD_EXE_FORMAT:
65
+ case ERROR_ITERATED_DATA_EXCEEDS_64k:
66
+ case ERROR_INVALID_MINALLOCSIZE:
67
+ case ERROR_DYNLINK_FROM_INVALID_RING:
68
+ case ERROR_IOPL_NOT_ENABLED:
69
+ case ERROR_INVALID_SEGDPL:
70
+ case ERROR_AUTODATASEG_EXCEEDS_64k:
71
+ case ERROR_RING2SEG_MUST_BE_MOVABLE:
72
+ case ERROR_RELOC_CHAIN_XEEDS_SEGLIM:
73
+ case ERROR_INFLOOP_IN_RELOC_CHAIN:
74
+ errno = ENOEXEC;
75
+ break;
76
+ case ERROR_INVALID_HANDLE:
77
+ case ERROR_INVALID_TARGET_HANDLE:
78
+ case ERROR_DIRECT_ACCESS_HANDLE:
79
+ errno = EBADF;
80
+ break;
81
+ case ERROR_WAIT_NO_CHILDREN:
82
+ case ERROR_CHILD_NOT_COMPLETE:
83
+ errno = ECHILD;
84
+ break;
85
+ case ERROR_NO_PROC_SLOTS:
86
+ case ERROR_MAX_THRDS_REACHED:
87
+ case ERROR_NESTING_NOT_ALLOWED:
88
+ errno = EAGAIN;
89
+ break;
90
+ case ERROR_ARENA_TRASHED:
91
+ case ERROR_NOT_ENOUGH_MEMORY:
92
+ case ERROR_INVALID_BLOCK:
93
+ case ERROR_NOT_ENOUGH_QUOTA:
94
+ errno = ENOMEM;
95
+ break;
96
+ case ERROR_ACCESS_DENIED:
97
+ case ERROR_CURRENT_DIRECTORY:
98
+ case ERROR_WRITE_PROTECT:
99
+ case ERROR_BAD_UNIT:
100
+ case ERROR_NOT_READY:
101
+ case ERROR_BAD_COMMAND:
102
+ case ERROR_CRC:
103
+ case ERROR_BAD_LENGTH:
104
+ case ERROR_SEEK:
105
+ case ERROR_NOT_DOS_DISK:
106
+ case ERROR_SECTOR_NOT_FOUND:
107
+ case ERROR_OUT_OF_PAPER:
108
+ case ERROR_WRITE_FAULT:
109
+ case ERROR_READ_FAULT:
110
+ case ERROR_GEN_FAILURE:
111
+ case ERROR_SHARING_VIOLATION:
112
+ case ERROR_LOCK_VIOLATION:
113
+ case ERROR_WRONG_DISK:
114
+ case ERROR_SHARING_BUFFER_EXCEEDED:
115
+ case ERROR_NETWORK_ACCESS_DENIED:
116
+ case ERROR_CANNOT_MAKE:
117
+ case ERROR_FAIL_I24:
118
+ case ERROR_DRIVE_LOCKED:
119
+ case ERROR_SEEK_ON_DEVICE:
120
+ case ERROR_NOT_LOCKED:
121
+ case ERROR_LOCK_FAILED:
122
+ errno = EACCES;
123
+ break;
124
+ case ERROR_FILE_EXISTS:
125
+ case ERROR_ALREADY_EXISTS:
126
+ errno = EEXIST;
127
+ break;
128
+ case ERROR_NOT_SAME_DEVICE:
129
+ errno = EXDEV;
130
+ break;
131
+ case ERROR_INVALID_FUNCTION:
132
+ case ERROR_INVALID_ACCESS:
133
+ case ERROR_INVALID_DATA:
134
+ case ERROR_INVALID_PARAMETER:
135
+ case ERROR_NEGATIVE_SEEK:
136
+ errno = EINVAL;
137
+ break;
138
+ case ERROR_TOO_MANY_OPEN_FILES:
139
+ errno = EMFILE;
140
+ break;
141
+ case ERROR_DISK_FULL:
142
+ errno = ENOSPC;
143
+ break;
144
+ case ERROR_BROKEN_PIPE:
145
+ errno = EPIPE;
146
+ break;
147
+ case ERROR_DIR_NOT_EMPTY:
148
+ errno = ENOTEMPTY;
149
+ break;
150
+ default:
151
+ errno = EINVAL;
152
+ }
153
+ }
154
+
155
+ GIT_INLINE(bool) last_error_retryable(void)
156
+ {
157
+ int os_error = GetLastError();
158
+
159
+ return (os_error == ERROR_SHARING_VIOLATION ||
160
+ os_error == ERROR_ACCESS_DENIED);
161
+ }
162
+
163
+ #define do_with_retries(fn, remediation) \
164
+ do { \
165
+ int __tries, __ret; \
166
+ for (__tries = 0; __tries < git_win32__retries; __tries++) { \
167
+ if (__tries && (__ret = (remediation)) != 0) \
168
+ return __ret; \
169
+ if ((__ret = (fn)) != GIT_RETRY) \
170
+ return __ret; \
171
+ Sleep(5); \
172
+ } \
173
+ return -1; \
174
+ } while (0) \
175
+
176
+ static int ensure_writable(wchar_t *path)
177
+ {
178
+ DWORD attrs;
179
+
180
+ if ((attrs = GetFileAttributesW(path)) == INVALID_FILE_ATTRIBUTES)
181
+ goto on_error;
182
+
183
+ if ((attrs & FILE_ATTRIBUTE_READONLY) == 0)
184
+ return 0;
185
+
186
+ if (!SetFileAttributesW(path, (attrs & ~FILE_ATTRIBUTE_READONLY)))
187
+ goto on_error;
188
+
189
+ return 0;
190
+
191
+ on_error:
192
+ set_errno();
193
+ return -1;
194
+ }
195
+
47
196
  /**
48
197
  * Truncate or extend file.
49
198
  *
@@ -89,30 +238,34 @@ int p_link(const char *old, const char *new)
89
238
  return -1;
90
239
  }
91
240
 
92
- int p_unlink(const char *path)
241
+ GIT_INLINE(int) unlink_once(const wchar_t *path)
93
242
  {
94
- git_win32_path buf;
95
- int error;
243
+ if (DeleteFileW(path))
244
+ return 0;
96
245
 
97
- if (git_win32_path_from_utf8(buf, path) < 0)
98
- return -1;
246
+ if (last_error_retryable())
247
+ return GIT_RETRY;
99
248
 
100
- error = _wunlink(buf);
249
+ set_errno();
250
+ return -1;
251
+ }
101
252
 
102
- /* If the file could not be deleted because it was
103
- * read-only, clear the bit and try again */
104
- if (error == -1 && errno == EACCES) {
105
- _wchmod(buf, 0666);
106
- error = _wunlink(buf);
107
- }
253
+ int p_unlink(const char *path)
254
+ {
255
+ git_win32_path wpath;
108
256
 
109
- return error;
257
+ if (git_win32_path_from_utf8(wpath, path) < 0)
258
+ return -1;
259
+
260
+ do_with_retries(unlink_once(wpath), ensure_writable(wpath));
110
261
  }
111
262
 
112
263
  int p_fsync(int fd)
113
264
  {
114
265
  HANDLE fh = (HANDLE)_get_osfhandle(fd);
115
266
 
267
+ p_fsync__cnt++;
268
+
116
269
  if (fh == INVALID_HANDLE_VALUE) {
117
270
  errno = EBADF;
118
271
  return -1;
@@ -210,44 +363,6 @@ int p_lstat_posixly(const char *filename, struct stat *buf)
210
363
  return do_lstat(filename, buf, true);
211
364
  }
212
365
 
213
- int p_utimes(const char *filename, const struct p_timeval times[2])
214
- {
215
- int fd, error;
216
-
217
- if ((fd = p_open(filename, O_RDWR)) < 0)
218
- return fd;
219
-
220
- error = p_futimes(fd, times);
221
-
222
- close(fd);
223
- return error;
224
- }
225
-
226
- int p_futimes(int fd, const struct p_timeval times[2])
227
- {
228
- HANDLE handle;
229
- FILETIME atime = {0}, mtime = {0};
230
-
231
- if (times == NULL) {
232
- SYSTEMTIME st;
233
-
234
- GetSystemTime(&st);
235
- SystemTimeToFileTime(&st, &atime);
236
- SystemTimeToFileTime(&st, &mtime);
237
- } else {
238
- git_win32__timeval_to_filetime(&atime, times[0]);
239
- git_win32__timeval_to_filetime(&mtime, times[1]);
240
- }
241
-
242
- if ((handle = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE)
243
- return -1;
244
-
245
- if (SetFileTime(handle, NULL, &atime, &mtime) == 0)
246
- return -1;
247
-
248
- return 0;
249
- }
250
-
251
366
  int p_readlink(const char *path, char *buf, size_t bufsiz)
252
367
  {
253
368
  git_win32_path path_w, target_w;
@@ -280,12 +395,91 @@ int p_symlink(const char *old, const char *new)
280
395
  return git_futils_fake_symlink(old, new);
281
396
  }
282
397
 
398
+ struct open_opts {
399
+ DWORD access;
400
+ DWORD sharing;
401
+ SECURITY_ATTRIBUTES security;
402
+ DWORD creation_disposition;
403
+ DWORD attributes;
404
+ int osf_flags;
405
+ };
406
+
407
+ GIT_INLINE(void) open_opts_from_posix(struct open_opts *opts, int flags, mode_t mode)
408
+ {
409
+ memset(opts, 0, sizeof(struct open_opts));
410
+
411
+ switch (flags & (O_WRONLY | O_RDWR)) {
412
+ case O_WRONLY:
413
+ opts->access = GENERIC_WRITE;
414
+ break;
415
+ case O_RDWR:
416
+ opts->access = GENERIC_READ | GENERIC_WRITE;
417
+ break;
418
+ default:
419
+ opts->access = GENERIC_READ;
420
+ break;
421
+ }
422
+
423
+ opts->sharing = (DWORD)git_win32__createfile_sharemode;
424
+
425
+ switch (flags & (O_CREAT | O_TRUNC | O_EXCL)) {
426
+ case O_CREAT | O_EXCL:
427
+ case O_CREAT | O_TRUNC | O_EXCL:
428
+ opts->creation_disposition = CREATE_NEW;
429
+ break;
430
+ case O_CREAT | O_TRUNC:
431
+ opts->creation_disposition = CREATE_ALWAYS;
432
+ break;
433
+ case O_TRUNC:
434
+ opts->creation_disposition = TRUNCATE_EXISTING;
435
+ break;
436
+ case O_CREAT:
437
+ opts->creation_disposition = OPEN_ALWAYS;
438
+ break;
439
+ default:
440
+ opts->creation_disposition = OPEN_EXISTING;
441
+ break;
442
+ }
443
+
444
+ opts->attributes = ((flags & O_CREAT) && !(mode & S_IWRITE)) ?
445
+ FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL;
446
+ opts->osf_flags = flags & (O_RDONLY | O_APPEND);
447
+
448
+ opts->security.nLength = sizeof(SECURITY_ATTRIBUTES);
449
+ opts->security.lpSecurityDescriptor = NULL;
450
+ opts->security.bInheritHandle = 0;
451
+ }
452
+
453
+ GIT_INLINE(int) open_once(
454
+ const wchar_t *path,
455
+ struct open_opts *opts)
456
+ {
457
+ int fd;
458
+
459
+ HANDLE handle = CreateFileW(path, opts->access, opts->sharing,
460
+ &opts->security, opts->creation_disposition, opts->attributes, 0);
461
+
462
+ if (handle == INVALID_HANDLE_VALUE) {
463
+ if (last_error_retryable())
464
+ return GIT_RETRY;
465
+
466
+ set_errno();
467
+ return -1;
468
+ }
469
+
470
+ if ((fd = _open_osfhandle((intptr_t)handle, opts->osf_flags)) < 0)
471
+ CloseHandle(handle);
472
+
473
+ return fd;
474
+ }
475
+
283
476
  int p_open(const char *path, int flags, ...)
284
477
  {
285
- git_win32_path buf;
478
+ git_win32_path wpath;
286
479
  mode_t mode = 0;
480
+ struct open_opts opts = {0};
287
481
 
288
- if (git_win32_path_from_utf8(buf, path) < 0)
482
+ if (git_win32_path_from_utf8(wpath, path) < 0)
289
483
  return -1;
290
484
 
291
485
  if (flags & O_CREAT) {
@@ -296,19 +490,83 @@ int p_open(const char *path, int flags, ...)
296
490
  va_end(arg_list);
297
491
  }
298
492
 
299
- return _wopen(buf, flags | STANDARD_OPEN_FLAGS, mode & WIN32_MODE_MASK);
493
+ open_opts_from_posix(&opts, flags, mode);
494
+
495
+ do_with_retries(
496
+ open_once(wpath, &opts),
497
+ 0);
300
498
  }
301
499
 
302
500
  int p_creat(const char *path, mode_t mode)
303
501
  {
304
- git_win32_path buf;
502
+ return p_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
503
+ }
305
504
 
306
- if (git_win32_path_from_utf8(buf, path) < 0)
505
+ int p_utimes(const char *path, const struct p_timeval times[2])
506
+ {
507
+ git_win32_path wpath;
508
+ int fd, error;
509
+ DWORD attrs_orig, attrs_new = 0;
510
+ struct open_opts opts = { 0 };
511
+
512
+ if (git_win32_path_from_utf8(wpath, path) < 0)
307
513
  return -1;
308
514
 
309
- return _wopen(buf,
310
- _O_WRONLY | _O_CREAT | _O_TRUNC | STANDARD_OPEN_FLAGS,
311
- mode & WIN32_MODE_MASK);
515
+ attrs_orig = GetFileAttributesW(wpath);
516
+
517
+ if (attrs_orig & FILE_ATTRIBUTE_READONLY) {
518
+ attrs_new = attrs_orig & ~FILE_ATTRIBUTE_READONLY;
519
+
520
+ if (!SetFileAttributesW(wpath, attrs_new)) {
521
+ giterr_set(GITERR_OS, "failed to set attributes");
522
+ return -1;
523
+ }
524
+ }
525
+
526
+ open_opts_from_posix(&opts, O_RDWR, 0);
527
+
528
+ if ((fd = open_once(wpath, &opts)) < 0) {
529
+ error = -1;
530
+ goto done;
531
+ }
532
+
533
+ error = p_futimes(fd, times);
534
+ close(fd);
535
+
536
+ done:
537
+ if (attrs_orig != attrs_new) {
538
+ DWORD os_error = GetLastError();
539
+ SetFileAttributesW(wpath, attrs_orig);
540
+ SetLastError(os_error);
541
+ }
542
+
543
+ return error;
544
+ }
545
+
546
+ int p_futimes(int fd, const struct p_timeval times[2])
547
+ {
548
+ HANDLE handle;
549
+ FILETIME atime = { 0 }, mtime = { 0 };
550
+
551
+ if (times == NULL) {
552
+ SYSTEMTIME st;
553
+
554
+ GetSystemTime(&st);
555
+ SystemTimeToFileTime(&st, &atime);
556
+ SystemTimeToFileTime(&st, &mtime);
557
+ }
558
+ else {
559
+ git_win32__timeval_to_filetime(&atime, times[0]);
560
+ git_win32__timeval_to_filetime(&mtime, times[1]);
561
+ }
562
+
563
+ if ((handle = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE)
564
+ return -1;
565
+
566
+ if (SetFileTime(handle, NULL, &atime, &mtime) == 0)
567
+ return -1;
568
+
569
+ return 0;
312
570
  }
313
571
 
314
572
  int p_getcwd(char *buffer_out, size_t size)
@@ -581,62 +839,27 @@ int p_access(const char* path, mode_t mode)
581
839
  return _waccess(buf, mode & WIN32_MODE_MASK);
582
840
  }
583
841
 
584
- static int ensure_writable(wchar_t *fpath)
842
+ GIT_INLINE(int) rename_once(const wchar_t *from, const wchar_t *to)
585
843
  {
586
- DWORD attrs;
587
-
588
- attrs = GetFileAttributesW(fpath);
589
- if (attrs == INVALID_FILE_ATTRIBUTES) {
590
- if (GetLastError() == ERROR_FILE_NOT_FOUND)
591
- return 0;
592
-
593
- giterr_set(GITERR_OS, "failed to get attributes");
594
- return -1;
595
- }
596
-
597
- if (!(attrs & FILE_ATTRIBUTE_READONLY))
844
+ if (MoveFileExW(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
598
845
  return 0;
599
846
 
600
- attrs &= ~FILE_ATTRIBUTE_READONLY;
601
- if (!SetFileAttributesW(fpath, attrs)) {
602
- giterr_set(GITERR_OS, "failed to set attributes");
603
- return -1;
604
- }
847
+ if (last_error_retryable())
848
+ return GIT_RETRY;
605
849
 
606
- return 0;
850
+ set_errno();
851
+ return -1;
607
852
  }
608
853
 
609
854
  int p_rename(const char *from, const char *to)
610
855
  {
611
- git_win32_path wfrom;
612
- git_win32_path wto;
613
- int rename_tries;
614
- int rename_succeeded;
615
- int error;
856
+ git_win32_path wfrom, wto;
616
857
 
617
858
  if (git_win32_path_from_utf8(wfrom, from) < 0 ||
618
859
  git_win32_path_from_utf8(wto, to) < 0)
619
860
  return -1;
620
861
 
621
- /* wait up to 50ms if file is locked by another thread or process */
622
- rename_tries = 0;
623
- rename_succeeded = 0;
624
- while (rename_tries < 10) {
625
- if (ensure_writable(wto) == 0 &&
626
- MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) != 0) {
627
- rename_succeeded = 1;
628
- break;
629
- }
630
-
631
- error = GetLastError();
632
- if (error == ERROR_SHARING_VIOLATION || error == ERROR_ACCESS_DENIED) {
633
- Sleep(5);
634
- rename_tries++;
635
- } else
636
- break;
637
- }
638
-
639
- return rename_succeeded ? 0 : -1;
862
+ do_with_retries(rename_once(wfrom, wto), ensure_writable(wto));
640
863
  }
641
864
 
642
865
  int p_recv(GIT_SOCKET socket, void *buffer, size_t length, int flags)