rugged 0.23.0b1 → 0.23.0b2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/rugged_note.c +7 -2
  3. data/ext/rugged/rugged_revwalk.c +321 -145
  4. data/lib/rugged/version.rb +1 -1
  5. data/vendor/libgit2/CMakeLists.txt +83 -8
  6. data/vendor/libgit2/cmake/Modules/FindCoreFoundation.cmake +9 -0
  7. data/vendor/libgit2/cmake/Modules/FindIconv.cmake +0 -3
  8. data/vendor/libgit2/cmake/Modules/FindSecurity.cmake +9 -0
  9. data/vendor/libgit2/deps/winhttp/urlmon.h +45 -0
  10. data/vendor/libgit2/deps/winhttp/winhttp.def +29 -0
  11. data/vendor/libgit2/deps/winhttp/winhttp.h +592 -0
  12. data/vendor/libgit2/deps/winhttp/winhttp64.def +29 -0
  13. data/vendor/libgit2/include/git2/diff.h +6 -1
  14. data/vendor/libgit2/include/git2/index.h +1 -1
  15. data/vendor/libgit2/include/git2/merge.h +2 -1
  16. data/vendor/libgit2/include/git2/notes.h +2 -2
  17. data/vendor/libgit2/include/git2/pack.h +12 -0
  18. data/vendor/libgit2/include/git2/push.h +30 -0
  19. data/vendor/libgit2/include/git2/rebase.h +36 -16
  20. data/vendor/libgit2/include/git2/remote.h +6 -0
  21. data/vendor/libgit2/include/git2/reset.h +2 -2
  22. data/vendor/libgit2/include/git2/revwalk.h +10 -8
  23. data/vendor/libgit2/include/git2/submodule.h +16 -0
  24. data/vendor/libgit2/include/git2/sys/transport.h +12 -4
  25. data/vendor/libgit2/include/git2/types.h +1 -0
  26. data/vendor/libgit2/src/attr.c +3 -3
  27. data/vendor/libgit2/src/attr_file.c +24 -3
  28. data/vendor/libgit2/src/attr_file.h +3 -1
  29. data/vendor/libgit2/src/checkout.c +31 -7
  30. data/vendor/libgit2/src/config.c +5 -6
  31. data/vendor/libgit2/src/config_file.c +533 -469
  32. data/vendor/libgit2/src/describe.c +1 -1
  33. data/vendor/libgit2/src/diff.c +20 -10
  34. data/vendor/libgit2/src/diff_driver.c +1 -1
  35. data/vendor/libgit2/src/diff_tform.c +8 -2
  36. data/vendor/libgit2/src/filter.c +6 -3
  37. data/vendor/libgit2/src/global.c +17 -15
  38. data/vendor/libgit2/src/global.h +3 -1
  39. data/vendor/libgit2/src/ignore.c +48 -8
  40. data/vendor/libgit2/src/ignore.h +1 -1
  41. data/vendor/libgit2/src/index.c +12 -8
  42. data/vendor/libgit2/src/iterator.c +133 -12
  43. data/vendor/libgit2/src/netops.h +2 -2
  44. data/vendor/libgit2/src/notes.c +40 -21
  45. data/vendor/libgit2/src/openssl_stream.c +5 -1
  46. data/vendor/libgit2/src/pack-objects.c +36 -0
  47. data/vendor/libgit2/src/path.c +277 -140
  48. data/vendor/libgit2/src/path.h +132 -60
  49. data/vendor/libgit2/src/posix.h +0 -1
  50. data/vendor/libgit2/src/push.c +43 -4
  51. data/vendor/libgit2/src/push.h +8 -1
  52. data/vendor/libgit2/src/rebase.c +139 -119
  53. data/vendor/libgit2/src/reflog.c +1 -1
  54. data/vendor/libgit2/src/refs.c +3 -5
  55. data/vendor/libgit2/src/remote.c +6 -5
  56. data/vendor/libgit2/src/repository.c +7 -3
  57. data/vendor/libgit2/src/reset.c +3 -3
  58. data/vendor/libgit2/src/revwalk.c +26 -2
  59. data/vendor/libgit2/src/settings.c +3 -3
  60. data/vendor/libgit2/src/stransport_stream.c +249 -0
  61. data/vendor/libgit2/src/stransport_stream.h +14 -0
  62. data/vendor/libgit2/src/submodule.c +26 -2
  63. data/vendor/libgit2/src/tls_stream.c +28 -0
  64. data/vendor/libgit2/src/tls_stream.h +21 -0
  65. data/vendor/libgit2/src/transport.c +4 -4
  66. data/vendor/libgit2/src/transports/git.c +4 -1
  67. data/vendor/libgit2/src/transports/http.c +6 -4
  68. data/vendor/libgit2/src/transports/local.c +2 -1
  69. data/vendor/libgit2/src/transports/smart.c +1 -1
  70. data/vendor/libgit2/src/transports/ssh.c +5 -1
  71. data/vendor/libgit2/src/transports/winhttp.c +30 -23
  72. data/vendor/libgit2/src/tree.c +2 -2
  73. data/vendor/libgit2/src/unix/posix.h +1 -0
  74. data/vendor/libgit2/src/util.h +117 -0
  75. data/vendor/libgit2/src/win32/buffer.c +55 -0
  76. data/vendor/libgit2/src/win32/buffer.h +18 -0
  77. data/vendor/libgit2/src/win32/path_w32.c +75 -0
  78. data/vendor/libgit2/src/win32/path_w32.h +3 -0
  79. data/vendor/libgit2/src/win32/posix.h +2 -2
  80. data/vendor/libgit2/src/win32/posix_w32.c +2 -118
  81. data/vendor/libgit2/src/win32/pthread.c +2 -0
  82. data/vendor/libgit2/src/win32/utf-conv.c +0 -4
  83. data/vendor/libgit2/src/win32/utf-conv.h +4 -0
  84. data/vendor/libgit2/src/win32/w32_util.h +72 -0
  85. metadata +14 -2
@@ -17,19 +17,12 @@
17
17
  #include "repository.h"
18
18
 
19
19
  #include <wincrypt.h>
20
- #pragma comment(lib, "crypt32")
21
20
  #include <winhttp.h>
22
- #pragma comment(lib, "winhttp")
23
-
24
- #include <strsafe.h>
25
21
 
26
22
  /* For IInternetSecurityManager zone check */
27
23
  #include <objbase.h>
28
24
  #include <urlmon.h>
29
25
 
30
- /* For UuidCreate */
31
- #pragma comment(lib, "rpcrt4")
32
-
33
26
  #define WIDEN2(s) L ## s
34
27
  #define WIDEN(s) WIDEN2(s)
35
28
 
@@ -43,7 +36,6 @@
43
36
  #define WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH 0
44
37
  #endif
45
38
 
46
- static const char *prefix_http = "http://";
47
39
  static const char *prefix_https = "https://";
48
40
  static const char *upload_pack_service = "upload-pack";
49
41
  static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack";
@@ -59,6 +51,13 @@ static const int no_check_cert_flags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
59
51
  SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
60
52
  SECURITY_FLAG_IGNORE_UNKNOWN_CA;
61
53
 
54
+ #if defined(__MINGW32__)
55
+ const CLSID CLSID_InternetSecurityManager = { 0x7B8A2D94, 0x0AC9, 0x11D1,
56
+ { 0x89, 0x6C, 0x00, 0xC0, 0x4F, 0xB6, 0xBF, 0xC4 } };
57
+ const IID IID_IInternetSecurityManager = { 0x79EAC9EE, 0xBAF9, 0x11CE,
58
+ { 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B } };
59
+ #endif
60
+
62
61
  #define OWNING_SUBTRANSPORT(s) ((winhttp_subtransport *)(s)->parent.subtransport)
63
62
 
64
63
  typedef enum {
@@ -272,7 +271,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
272
271
  git_buf buf = GIT_BUF_INIT;
273
272
  char *proxy_url = NULL;
274
273
  wchar_t ct[MAX_CONTENT_TYPE_LEN];
275
- wchar_t *types[] = { L"*/*", NULL };
274
+ LPCWSTR types[] = { L"*/*", NULL };
276
275
  BOOL peerdist = FALSE;
277
276
  int error = -1;
278
277
  unsigned long disable_redirects = WINHTTP_DISABLE_REDIRECTS;
@@ -551,8 +550,7 @@ static int winhttp_close_connection(winhttp_subtransport *t)
551
550
  }
552
551
 
553
552
  static int winhttp_connect(
554
- winhttp_subtransport *t,
555
- const char *url)
553
+ winhttp_subtransport *t)
556
554
  {
557
555
  wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")";
558
556
  wchar_t *wide_host;
@@ -561,8 +559,6 @@ static int winhttp_connect(
561
559
  int default_timeout = TIMEOUT_INFINITE;
562
560
  int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
563
561
 
564
- GIT_UNUSED(url);
565
-
566
562
  t->session = NULL;
567
563
  t->connection = NULL;
568
564
 
@@ -860,7 +856,7 @@ replay:
860
856
 
861
857
  winhttp_close_connection(t);
862
858
 
863
- if (winhttp_connect(t, location8) < 0)
859
+ if (winhttp_connect(t) < 0)
864
860
  return -1;
865
861
  }
866
862
 
@@ -963,7 +959,6 @@ static int winhttp_stream_write_single(
963
959
  size_t len)
964
960
  {
965
961
  winhttp_stream *s = (winhttp_stream *)stream;
966
- winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
967
962
  DWORD bytes_written;
968
963
  int error;
969
964
 
@@ -998,7 +993,7 @@ static int put_uuid_string(LPWSTR buffer, size_t buffer_len_cch)
998
993
  {
999
994
  UUID uuid;
1000
995
  RPC_STATUS status = UuidCreate(&uuid);
1001
- HRESULT result;
996
+ int result;
1002
997
 
1003
998
  if (RPC_S_OK != status &&
1004
999
  RPC_S_UUID_LOCAL_ONLY != status &&
@@ -1012,14 +1007,17 @@ static int put_uuid_string(LPWSTR buffer, size_t buffer_len_cch)
1012
1007
  return -1;
1013
1008
  }
1014
1009
 
1015
- result = StringCbPrintfW(
1016
- buffer, buffer_len_cch,
1010
+ #if !defined(__MINGW32__) || defined(MINGW_HAS_SECURE_API)
1011
+ result = swprintf_s(buffer, buffer_len_cch,
1012
+ #else
1013
+ result = wsprintfW(buffer,
1014
+ #endif
1017
1015
  L"%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x",
1018
1016
  uuid.Data1, uuid.Data2, uuid.Data3,
1019
1017
  uuid.Data4[0], uuid.Data4[1], uuid.Data4[2], uuid.Data4[3],
1020
1018
  uuid.Data4[4], uuid.Data4[5], uuid.Data4[6], uuid.Data4[7]);
1021
1019
 
1022
- if (FAILED(result)) {
1020
+ if (result < UUID_LENGTH_CCH) {
1023
1021
  giterr_set(GITERR_OS, "Unable to generate name for temp file");
1024
1022
  return -1;
1025
1023
  }
@@ -1053,7 +1051,6 @@ static int winhttp_stream_write_buffered(
1053
1051
  size_t len)
1054
1052
  {
1055
1053
  winhttp_stream *s = (winhttp_stream *)stream;
1056
- winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
1057
1054
  DWORD bytes_written;
1058
1055
 
1059
1056
  if (!s->request && winhttp_stream_connect(s) < 0)
@@ -1135,7 +1132,7 @@ static int winhttp_stream_write_chunked(
1135
1132
  }
1136
1133
  else {
1137
1134
  /* Append as much to the buffer as we can */
1138
- int count = min(CACHED_POST_BODY_BUF_SIZE - s->chunk_buffer_len, (int)len);
1135
+ int count = (int)min(CACHED_POST_BODY_BUF_SIZE - s->chunk_buffer_len, len);
1139
1136
 
1140
1137
  if (!s->chunk_buffer)
1141
1138
  s->chunk_buffer = git__malloc(CACHED_POST_BODY_BUF_SIZE);
@@ -1195,6 +1192,8 @@ static int winhttp_uploadpack_ls(
1195
1192
  winhttp_subtransport *t,
1196
1193
  winhttp_stream *s)
1197
1194
  {
1195
+ GIT_UNUSED(t);
1196
+
1198
1197
  s->service = upload_pack_service;
1199
1198
  s->service_url = upload_pack_ls_service_url;
1200
1199
  s->verb = get_verb;
@@ -1206,6 +1205,8 @@ static int winhttp_uploadpack(
1206
1205
  winhttp_subtransport *t,
1207
1206
  winhttp_stream *s)
1208
1207
  {
1208
+ GIT_UNUSED(t);
1209
+
1209
1210
  s->service = upload_pack_service;
1210
1211
  s->service_url = upload_pack_service_url;
1211
1212
  s->verb = post_verb;
@@ -1217,6 +1218,8 @@ static int winhttp_receivepack_ls(
1217
1218
  winhttp_subtransport *t,
1218
1219
  winhttp_stream *s)
1219
1220
  {
1221
+ GIT_UNUSED(t);
1222
+
1220
1223
  s->service = receive_pack_service;
1221
1224
  s->service_url = receive_pack_ls_service_url;
1222
1225
  s->verb = get_verb;
@@ -1228,6 +1231,8 @@ static int winhttp_receivepack(
1228
1231
  winhttp_subtransport *t,
1229
1232
  winhttp_stream *s)
1230
1233
  {
1234
+ GIT_UNUSED(t);
1235
+
1231
1236
  /* WinHTTP only supports Transfer-Encoding: chunked
1232
1237
  * on Windows Vista (NT 6.0) and higher. */
1233
1238
  s->chunked = git_has_win32_version(6, 0, 0);
@@ -1256,7 +1261,7 @@ static int winhttp_action(
1256
1261
 
1257
1262
  if (!t->connection)
1258
1263
  if ((ret = gitno_connection_data_from_url(&t->connection_data, url, NULL)) < 0 ||
1259
- (ret = winhttp_connect(t, url)) < 0)
1264
+ (ret = winhttp_connect(t)) < 0)
1260
1265
  return ret;
1261
1266
 
1262
1267
  if (winhttp_stream_alloc(t, &s) < 0)
@@ -1322,10 +1327,12 @@ static void winhttp_free(git_smart_subtransport *subtransport)
1322
1327
  git__free(t);
1323
1328
  }
1324
1329
 
1325
- int git_smart_subtransport_http(git_smart_subtransport **out, git_transport *owner)
1330
+ int git_smart_subtransport_http(git_smart_subtransport **out, git_transport *owner, void *param)
1326
1331
  {
1327
1332
  winhttp_subtransport *t;
1328
1333
 
1334
+ GIT_UNUSED(param);
1335
+
1329
1336
  if (!out)
1330
1337
  return -1;
1331
1338
 
@@ -858,7 +858,7 @@ int git_tree_entry_bypath(
858
858
 
859
859
  if (entry == NULL) {
860
860
  giterr_set(GITERR_TREE,
861
- "The path '%s' does not exist in the given tree", path);
861
+ "the path '%.*s' does not exist in the given tree", filename_len, path);
862
862
  return GIT_ENOTFOUND;
863
863
  }
864
864
 
@@ -868,7 +868,7 @@ int git_tree_entry_bypath(
868
868
  * then this entry *must* be a tree */
869
869
  if (!git_tree_entry__is_tree(entry)) {
870
870
  giterr_set(GITERR_TREE,
871
- "The path '%s' does not exist in the given tree", path);
871
+ "the path '%.*s' exists but is not a tree", filename_len, path);
872
872
  return GIT_ENOTFOUND;
873
873
  }
874
874
 
@@ -8,6 +8,7 @@
8
8
  #define INCLUDE_posix__unix_h__
9
9
 
10
10
  #include <stdio.h>
11
+ #include <dirent.h>
11
12
  #include <sys/param.h>
12
13
 
13
14
  typedef int GIT_SOCKET;
@@ -7,6 +7,36 @@
7
7
  #ifndef INCLUDE_util_h__
8
8
  #define INCLUDE_util_h__
9
9
 
10
+ #if defined(GIT_MSVC_CRTDBG)
11
+ /* Enable MSVC CRTDBG memory leak reporting.
12
+ *
13
+ * We DO NOT use the "_CRTDBG_MAP_ALLOC" macro described in the MSVC
14
+ * documentation because all allocs/frees in libgit2 already go through
15
+ * the "git__" routines defined in this file. Simply using the normal
16
+ * reporting mechanism causes all leaks to be attributed to a routine
17
+ * here in util.h (ie, the actual call to calloc()) rather than the
18
+ * caller of git__calloc().
19
+ *
20
+ * Therefore, we declare a set of "git__crtdbg__" routines to replace
21
+ * the corresponding "git__" routines and re-define the "git__" symbols
22
+ * as macros. This allows us to get and report the file:line info of
23
+ * the real caller.
24
+ *
25
+ * We DO NOT replace the "git__free" routine because it needs to remain
26
+ * a function pointer because it is used as a function argument when
27
+ * setting up various structure "destructors".
28
+ *
29
+ * We also DO NOT use the "_CRTDBG_MAP_ALLOC" macro because it causes
30
+ * "free" to be remapped to "_free_dbg" and this causes problems for
31
+ * structures which define a field named "free".
32
+ *
33
+ * Finally, CRTDBG must be explicitly enabled and configured at program
34
+ * startup. See tests/main.c for an example.
35
+ */
36
+ #include <stdlib.h>
37
+ #include <crtdbg.h>
38
+ #endif
39
+
10
40
  #include "common.h"
11
41
  #include "strnlen.h"
12
42
 
@@ -31,6 +61,91 @@
31
61
  */
32
62
  #define CONST_STRLEN(x) ((sizeof(x)/sizeof(x[0])) - 1)
33
63
 
64
+ #if defined(GIT_MSVC_CRTDBG)
65
+ GIT_INLINE(void *) git__crtdbg__malloc(size_t len, const char *file, int line)
66
+ {
67
+ void *ptr = _malloc_dbg(len, _NORMAL_BLOCK, file, line);
68
+ if (!ptr) giterr_set_oom();
69
+ return ptr;
70
+ }
71
+
72
+ GIT_INLINE(void *) git__crtdbg__calloc(size_t nelem, size_t elsize, const char *file, int line)
73
+ {
74
+ void *ptr = _calloc_dbg(nelem, elsize, _NORMAL_BLOCK, file, line);
75
+ if (!ptr) giterr_set_oom();
76
+ return ptr;
77
+ }
78
+
79
+ GIT_INLINE(char *) git__crtdbg__strdup(const char *str, const char *file, int line)
80
+ {
81
+ char *ptr = _strdup_dbg(str, _NORMAL_BLOCK, file, line);
82
+ if (!ptr) giterr_set_oom();
83
+ return ptr;
84
+ }
85
+
86
+ GIT_INLINE(char *) git__crtdbg__strndup(const char *str, size_t n, const char *file, int line)
87
+ {
88
+ size_t length = 0, alloclength;
89
+ char *ptr;
90
+
91
+ length = p_strnlen(str, n);
92
+
93
+ if (GIT_ADD_SIZET_OVERFLOW(&alloclength, length, 1) ||
94
+ !(ptr = git__crtdbg__malloc(alloclength, file, line)))
95
+ return NULL;
96
+
97
+ if (length)
98
+ memcpy(ptr, str, length);
99
+
100
+ ptr[length] = '\0';
101
+
102
+ return ptr;
103
+ }
104
+
105
+ GIT_INLINE(char *) git__crtdbg__substrdup(const char *start, size_t n, const char *file, int line)
106
+ {
107
+ char *ptr;
108
+ size_t alloclen;
109
+
110
+ if (GIT_ADD_SIZET_OVERFLOW(&alloclen, n, 1) ||
111
+ !(ptr = git__crtdbg__malloc(alloclen, file, line)))
112
+ return NULL;
113
+
114
+ memcpy(ptr, start, n);
115
+ ptr[n] = '\0';
116
+ return ptr;
117
+ }
118
+
119
+ GIT_INLINE(void *) git__crtdbg__realloc(void *ptr, size_t size, const char *file, int line)
120
+ {
121
+ void *new_ptr = _realloc_dbg(ptr, size, _NORMAL_BLOCK, file, line);
122
+ if (!new_ptr) giterr_set_oom();
123
+ return new_ptr;
124
+ }
125
+
126
+ GIT_INLINE(void *) git__crtdbg__reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line)
127
+ {
128
+ size_t newsize;
129
+ return GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize) ?
130
+ NULL : _realloc_dbg(ptr, newsize, _NORMAL_BLOCK, file, line);
131
+ }
132
+
133
+ GIT_INLINE(void *) git__crtdbg__mallocarray(size_t nelem, size_t elsize, const char *file, int line)
134
+ {
135
+ return git__crtdbg__reallocarray(NULL, nelem, elsize, file, line);
136
+ }
137
+
138
+ #define git__malloc(len) git__crtdbg__malloc(len, __FILE__, __LINE__)
139
+ #define git__calloc(nelem, elsize) git__crtdbg__calloc(nelem, elsize, __FILE__, __LINE__)
140
+ #define git__strdup(str) git__crtdbg__strdup(str, __FILE__, __LINE__)
141
+ #define git__strndup(str, n) git__crtdbg__strndup(str, n, __FILE__, __LINE__)
142
+ #define git__substrdup(str, n) git__crtdbg__substrdup(str, n, __FILE__, __LINE__)
143
+ #define git__realloc(ptr, size) git__crtdbg__realloc(ptr, size, __FILE__, __LINE__)
144
+ #define git__reallocarray(ptr, nelem, elsize) git__crtdbg__reallocarray(ptr, nelem, elsize, __FILE__, __LINE__)
145
+ #define git__mallocarray(nelem, elsize) git__crtdbg__mallocarray(nelem, elsize, __FILE__, __LINE__)
146
+
147
+ #else
148
+
34
149
  /*
35
150
  * Custom memory allocation wrappers
36
151
  * that set error code and error message
@@ -118,6 +233,8 @@ GIT_INLINE(void *) git__mallocarray(size_t nelem, size_t elsize)
118
233
  return git__reallocarray(NULL, nelem, elsize);
119
234
  }
120
235
 
236
+ #endif /* !MSVC_CTRDBG */
237
+
121
238
  GIT_INLINE(void) git__free(void *ptr)
122
239
  {
123
240
  free(ptr);
@@ -0,0 +1,55 @@
1
+ /*
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
+ *
4
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
5
+ * a Linking Exception. For full terms see the included COPYING file.
6
+ */
7
+
8
+ #include "common.h"
9
+ #include "buffer.h"
10
+ #include "../buffer.h"
11
+ #include "utf-conv.h"
12
+
13
+ GIT_INLINE(int) handle_wc_error(void)
14
+ {
15
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
16
+ errno = ENAMETOOLONG;
17
+ else
18
+ errno = EINVAL;
19
+
20
+ return -1;
21
+ }
22
+
23
+ int git_buf_put_w(git_buf *buf, const wchar_t *string_w, size_t len_w)
24
+ {
25
+ int utf8_len, utf8_write_len;
26
+ size_t new_size;
27
+
28
+ if (!len_w)
29
+ return 0;
30
+
31
+ assert(string_w);
32
+
33
+ /* Measure the string necessary for conversion */
34
+ if ((utf8_len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, string_w, len_w, NULL, 0, NULL, NULL)) == 0)
35
+ return 0;
36
+
37
+ assert(utf8_len > 0);
38
+
39
+ GITERR_CHECK_ALLOC_ADD(&new_size, buf->size, (size_t)utf8_len);
40
+ GITERR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
41
+
42
+ if (git_buf_grow(buf, new_size) < 0)
43
+ return -1;
44
+
45
+ if ((utf8_write_len = WideCharToMultiByte(
46
+ CP_UTF8, WC_ERR_INVALID_CHARS, string_w, len_w, &buf->ptr[buf->size], utf8_len, NULL, NULL)) == 0)
47
+ return handle_wc_error();
48
+
49
+ assert(utf8_write_len == utf8_len);
50
+
51
+ buf->size += utf8_write_len;
52
+ buf->ptr[buf->size] = '\0';
53
+ return 0;
54
+ }
55
+
@@ -0,0 +1,18 @@
1
+ /*
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
+ *
4
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
5
+ * a Linking Exception. For full terms see the included COPYING file.
6
+ */
7
+ #ifndef INCLUDE_git_win32_buffer_h__
8
+ #define INCLUDE_git_win32_buffer_h__
9
+
10
+ #include "../buffer.h"
11
+
12
+ /**
13
+ * Convert a wide character string to UTF-8 and append the results to the
14
+ * buffer.
15
+ */
16
+ int git_buf_put_w(git_buf *buf, const wchar_t *string_w, size_t len_w);
17
+
18
+ #endif
@@ -9,6 +9,9 @@
9
9
  #include "path.h"
10
10
  #include "path_w32.h"
11
11
  #include "utf-conv.h"
12
+ #include "posix.h"
13
+ #include "reparse.h"
14
+ #include "dir.h"
12
15
 
13
16
  #define PATH__NT_NAMESPACE L"\\\\?\\"
14
17
  #define PATH__NT_NAMESPACE_LEN 4
@@ -303,3 +306,75 @@ char *git_win32_path_8dot3_name(const char *path)
303
306
 
304
307
  return shortname;
305
308
  }
309
+
310
+ static bool path_is_volume(wchar_t *target, size_t target_len)
311
+ {
312
+ return (target_len && wcsncmp(target, L"\\??\\Volume{", 11) == 0);
313
+ }
314
+
315
+ /* On success, returns the length, in characters, of the path stored in dest.
316
+ * On failure, returns a negative value. */
317
+ int git_win32_path_readlink_w(git_win32_path dest, const git_win32_path path)
318
+ {
319
+ BYTE buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
320
+ GIT_REPARSE_DATA_BUFFER *reparse_buf = (GIT_REPARSE_DATA_BUFFER *)buf;
321
+ HANDLE handle = NULL;
322
+ DWORD ioctl_ret;
323
+ wchar_t *target;
324
+ size_t target_len;
325
+
326
+ int error = -1;
327
+
328
+ handle = CreateFileW(path, GENERIC_READ,
329
+ FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
330
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
331
+
332
+ if (handle == INVALID_HANDLE_VALUE) {
333
+ errno = ENOENT;
334
+ return -1;
335
+ }
336
+
337
+ if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0,
338
+ reparse_buf, sizeof(buf), &ioctl_ret, NULL)) {
339
+ errno = EINVAL;
340
+ goto on_error;
341
+ }
342
+
343
+ switch (reparse_buf->ReparseTag) {
344
+ case IO_REPARSE_TAG_SYMLINK:
345
+ target = reparse_buf->SymbolicLinkReparseBuffer.PathBuffer +
346
+ (reparse_buf->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR));
347
+ target_len = reparse_buf->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
348
+ break;
349
+ case IO_REPARSE_TAG_MOUNT_POINT:
350
+ target = reparse_buf->MountPointReparseBuffer.PathBuffer +
351
+ (reparse_buf->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR));
352
+ target_len = reparse_buf->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
353
+ break;
354
+ default:
355
+ errno = EINVAL;
356
+ goto on_error;
357
+ }
358
+
359
+ if (path_is_volume(target, target_len)) {
360
+ /* This path is a reparse point that represents another volume mounted
361
+ * at this location, it is not a symbolic link our input was canonical.
362
+ */
363
+ errno = EINVAL;
364
+ error = -1;
365
+ } else if (target_len) {
366
+ /* The path may need to have a prefix removed. */
367
+ target_len = git_win32__canonicalize_path(target, target_len);
368
+
369
+ /* Need one additional character in the target buffer
370
+ * for the terminating NULL. */
371
+ if (GIT_WIN_PATH_UTF16 > target_len) {
372
+ wcscpy(dest, target);
373
+ error = (int)target_len;
374
+ }
375
+ }
376
+
377
+ on_error:
378
+ CloseHandle(handle);
379
+ return error;
380
+ }
@@ -8,6 +8,7 @@
8
8
  #define INCLUDE_git_path_w32_h__
9
9
 
10
10
  #include "common.h"
11
+ #include "vector.h"
11
12
 
12
13
  /*
13
14
  * Provides a large enough buffer to support Windows paths: MAX_PATH is
@@ -79,4 +80,6 @@ extern int git_win32_path_to_utf8(git_win32_utf8_path dest, const wchar_t *src);
79
80
  */
80
81
  extern char *git_win32_path_8dot3_name(const char *path);
81
82
 
83
+ extern int git_win32_path_readlink_w(git_win32_path dest, const git_win32_path path);
84
+
82
85
  #endif
@@ -49,7 +49,7 @@ extern int p_ftruncate(int fd, git_off_t size);
49
49
  */
50
50
  extern int p_lstat_posixly(const char *filename, struct stat *buf);
51
51
 
52
- extern struct tm * p_localtime_r (const time_t *timer, struct tm *result);
53
- extern struct tm * p_gmtime_r (const time_t *timer, struct tm *result);
52
+ extern struct tm * p_localtime_r(const time_t *timer, struct tm *result);
53
+ extern struct tm * p_gmtime_r(const time_t *timer, struct tm *result);
54
54
 
55
55
  #endif
@@ -130,88 +130,6 @@ int p_fsync(int fd)
130
130
  return 0;
131
131
  }
132
132
 
133
- GIT_INLINE(time_t) filetime_to_time_t(const FILETIME *ft)
134
- {
135
- long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
136
- winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
137
- winTime /= 10000000; /* Nano to seconds resolution */
138
- return (time_t)winTime;
139
- }
140
-
141
- static bool path_is_volume(wchar_t *target, size_t target_len)
142
- {
143
- return (target_len && wcsncmp(target, L"\\??\\Volume{", 11) == 0);
144
- }
145
-
146
- /* On success, returns the length, in characters, of the path stored in dest.
147
- * On failure, returns a negative value. */
148
- static int readlink_w(
149
- git_win32_path dest,
150
- const git_win32_path path)
151
- {
152
- BYTE buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
153
- GIT_REPARSE_DATA_BUFFER *reparse_buf = (GIT_REPARSE_DATA_BUFFER *)buf;
154
- HANDLE handle = NULL;
155
- DWORD ioctl_ret;
156
- wchar_t *target;
157
- size_t target_len;
158
-
159
- int error = -1;
160
-
161
- handle = CreateFileW(path, GENERIC_READ,
162
- FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
163
- FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
164
-
165
- if (handle == INVALID_HANDLE_VALUE) {
166
- errno = ENOENT;
167
- return -1;
168
- }
169
-
170
- if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0,
171
- reparse_buf, sizeof(buf), &ioctl_ret, NULL)) {
172
- errno = EINVAL;
173
- goto on_error;
174
- }
175
-
176
- switch (reparse_buf->ReparseTag) {
177
- case IO_REPARSE_TAG_SYMLINK:
178
- target = reparse_buf->SymbolicLinkReparseBuffer.PathBuffer +
179
- (reparse_buf->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR));
180
- target_len = reparse_buf->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
181
- break;
182
- case IO_REPARSE_TAG_MOUNT_POINT:
183
- target = reparse_buf->MountPointReparseBuffer.PathBuffer +
184
- (reparse_buf->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR));
185
- target_len = reparse_buf->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
186
- break;
187
- default:
188
- errno = EINVAL;
189
- goto on_error;
190
- }
191
-
192
- if (path_is_volume(target, target_len)) {
193
- /* This path is a reparse point that represents another volume mounted
194
- * at this location, it is not a symbolic link our input was canonical.
195
- */
196
- errno = EINVAL;
197
- error = -1;
198
- } else if (target_len) {
199
- /* The path may need to have a prefix removed. */
200
- target_len = git_win32__canonicalize_path(target, target_len);
201
-
202
- /* Need one additional character in the target buffer
203
- * for the terminating NULL. */
204
- if (GIT_WIN_PATH_UTF16 > target_len) {
205
- wcscpy(dest, target);
206
- error = (int)target_len;
207
- }
208
- }
209
-
210
- on_error:
211
- CloseHandle(handle);
212
- return error;
213
- }
214
-
215
133
  #define WIN32_IS_WSEP(CH) ((CH) == L'/' || (CH) == L'\\')
216
134
 
217
135
  static int lstat_w(
@@ -222,44 +140,10 @@ static int lstat_w(
222
140
  WIN32_FILE_ATTRIBUTE_DATA fdata;
223
141
 
224
142
  if (GetFileAttributesExW(path, GetFileExInfoStandard, &fdata)) {
225
- int fMode = S_IREAD;
226
-
227
143
  if (!buf)
228
144
  return 0;
229
145
 
230
- if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
231
- fMode |= S_IFDIR;
232
- else
233
- fMode |= S_IFREG;
234
-
235
- if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
236
- fMode |= S_IWRITE;
237
-
238
- buf->st_ino = 0;
239
- buf->st_gid = 0;
240
- buf->st_uid = 0;
241
- buf->st_nlink = 1;
242
- buf->st_mode = (mode_t)fMode;
243
- buf->st_size = ((git_off_t)fdata.nFileSizeHigh << 32) + fdata.nFileSizeLow;
244
- buf->st_dev = buf->st_rdev = (_getdrive() - 1);
245
- buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
246
- buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
247
- buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
248
-
249
- if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
250
- git_win32_path target;
251
-
252
- if (readlink_w(target, path) >= 0) {
253
- buf->st_mode = (buf->st_mode & ~S_IFMT) | S_IFLNK;
254
-
255
- /* st_size gets the UTF-8 length of the target name, in bytes,
256
- * not counting the NULL terminator */
257
- if ((buf->st_size = git__utf16_to_8(NULL, 0, target)) < 0)
258
- return -1;
259
- }
260
- }
261
-
262
- return 0;
146
+ return git_win32__file_attribute_to_stat(buf, &fdata, path);
263
147
  }
264
148
 
265
149
  errno = ENOENT;
@@ -331,7 +215,7 @@ int p_readlink(const char *path, char *buf, size_t bufsiz)
331
215
  * we need to buffer the result on the stack. */
332
216
 
333
217
  if (git_win32_path_from_utf8(path_w, path) < 0 ||
334
- readlink_w(target_w, path_w) < 0 ||
218
+ git_win32_path_readlink_w(target_w, path_w) < 0 ||
335
219
  (len = git_win32_path_to_utf8(target, target_w)) < 0)
336
220
  return -1;
337
221
 
@@ -20,6 +20,8 @@ static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter)
20
20
 
21
21
  thread->result = thread->proc(thread->param);
22
22
 
23
+ git__free_tls_data();
24
+
23
25
  return CLEAN_THREAD_EXIT;
24
26
  }
25
27