rugged 0.21.4 → 0.22.0b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (224) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -5
  3. data/ext/rugged/extconf.rb +9 -9
  4. data/ext/rugged/rugged.c +4 -2
  5. data/ext/rugged/rugged.h +3 -7
  6. data/ext/rugged/rugged_blob.c +57 -0
  7. data/ext/rugged/rugged_cred.c +23 -0
  8. data/ext/rugged/rugged_index.c +6 -2
  9. data/ext/rugged/rugged_remote.c +65 -52
  10. data/ext/rugged/rugged_remote_collection.c +59 -10
  11. data/ext/rugged/rugged_repo.c +345 -11
  12. data/ext/rugged/rugged_revwalk.c +10 -0
  13. data/ext/rugged/rugged_submodule.c +1042 -0
  14. data/ext/rugged/rugged_submodule_collection.c +236 -0
  15. data/ext/rugged/rugged_tag_collection.c +70 -2
  16. data/ext/rugged/rugged_tree.c +29 -10
  17. data/lib/rugged.rb +3 -0
  18. data/lib/rugged/attributes.rb +41 -0
  19. data/lib/rugged/blob.rb +28 -0
  20. data/lib/rugged/diff.rb +0 -1
  21. data/lib/rugged/diff/line.rb +1 -3
  22. data/lib/rugged/patch.rb +12 -2
  23. data/lib/rugged/repository.rb +7 -0
  24. data/lib/rugged/submodule_collection.rb +48 -0
  25. data/lib/rugged/version.rb +1 -1
  26. data/vendor/libgit2/CMakeLists.txt +27 -3
  27. data/vendor/libgit2/cmake/Modules/FindGSSAPI.cmake +324 -0
  28. data/vendor/libgit2/deps/http-parser/http_parser.h +2 -0
  29. data/vendor/libgit2/deps/zlib/adler32.c +39 -29
  30. data/vendor/libgit2/deps/zlib/crc32.c +33 -50
  31. data/vendor/libgit2/deps/zlib/crc32.h +1 -1
  32. data/vendor/libgit2/deps/zlib/deflate.c +198 -65
  33. data/vendor/libgit2/deps/zlib/deflate.h +8 -4
  34. data/vendor/libgit2/deps/zlib/infback.c +640 -0
  35. data/vendor/libgit2/deps/zlib/inffast.c +3 -3
  36. data/vendor/libgit2/deps/zlib/inffixed.h +3 -3
  37. data/vendor/libgit2/deps/zlib/inflate.c +84 -52
  38. data/vendor/libgit2/deps/zlib/inftrees.c +15 -39
  39. data/vendor/libgit2/deps/zlib/trees.c +18 -36
  40. data/vendor/libgit2/deps/zlib/zconf.h +4 -0
  41. data/vendor/libgit2/deps/zlib/zlib.h +250 -95
  42. data/vendor/libgit2/deps/zlib/zutil.c +13 -10
  43. data/vendor/libgit2/deps/zlib/zutil.h +41 -62
  44. data/vendor/libgit2/include/git2.h +4 -0
  45. data/vendor/libgit2/include/git2/annotated_commit.h +99 -0
  46. data/vendor/libgit2/include/git2/attr.h +16 -13
  47. data/vendor/libgit2/include/git2/branch.h +11 -0
  48. data/vendor/libgit2/include/git2/buffer.h +16 -0
  49. data/vendor/libgit2/include/git2/checkout.h +12 -12
  50. data/vendor/libgit2/include/git2/cherrypick.h +15 -15
  51. data/vendor/libgit2/include/git2/clone.h +77 -69
  52. data/vendor/libgit2/include/git2/common.h +13 -1
  53. data/vendor/libgit2/include/git2/config.h +0 -14
  54. data/vendor/libgit2/include/git2/describe.h +162 -0
  55. data/vendor/libgit2/include/git2/diff.h +13 -8
  56. data/vendor/libgit2/include/git2/errors.h +5 -0
  57. data/vendor/libgit2/include/git2/global.h +38 -0
  58. data/vendor/libgit2/include/git2/merge.h +38 -64
  59. data/vendor/libgit2/include/git2/net.h +2 -2
  60. data/vendor/libgit2/include/git2/notes.h +17 -0
  61. data/vendor/libgit2/include/git2/oid.h +8 -4
  62. data/vendor/libgit2/include/git2/oidarray.h +40 -0
  63. data/vendor/libgit2/include/git2/rebase.h +261 -0
  64. data/vendor/libgit2/include/git2/reflog.h +1 -1
  65. data/vendor/libgit2/include/git2/remote.h +25 -47
  66. data/vendor/libgit2/include/git2/repository.h +4 -1
  67. data/vendor/libgit2/include/git2/reset.h +10 -1
  68. data/vendor/libgit2/include/git2/revert.h +1 -1
  69. data/vendor/libgit2/include/git2/revwalk.h +28 -23
  70. data/vendor/libgit2/include/git2/status.h +19 -15
  71. data/vendor/libgit2/include/git2/submodule.h +18 -0
  72. data/vendor/libgit2/include/git2/sys/config.h +0 -1
  73. data/vendor/libgit2/{src → include/git2/sys}/hashsig.h +11 -7
  74. data/vendor/libgit2/include/git2/sys/refdb_backend.h +13 -0
  75. data/vendor/libgit2/include/git2/sys/refs.h +0 -11
  76. data/vendor/libgit2/include/git2/sys/repository.h +13 -0
  77. data/vendor/libgit2/include/git2/sys/transport.h +352 -0
  78. data/vendor/libgit2/include/git2/threads.h +10 -20
  79. data/vendor/libgit2/include/git2/transaction.h +111 -0
  80. data/vendor/libgit2/include/git2/transport.h +79 -313
  81. data/vendor/libgit2/include/git2/tree.h +4 -2
  82. data/vendor/libgit2/include/git2/types.h +77 -8
  83. data/vendor/libgit2/include/git2/version.h +2 -2
  84. data/vendor/libgit2/src/annotated_commit.c +121 -0
  85. data/vendor/libgit2/src/annotated_commit.h +22 -0
  86. data/vendor/libgit2/src/attr.c +8 -4
  87. data/vendor/libgit2/src/attr_file.c +24 -2
  88. data/vendor/libgit2/src/blame.c +0 -1
  89. data/vendor/libgit2/src/branch.c +32 -3
  90. data/vendor/libgit2/src/buf_text.c +9 -5
  91. data/vendor/libgit2/src/buf_text.h +3 -2
  92. data/vendor/libgit2/src/buffer.c +67 -10
  93. data/vendor/libgit2/src/buffer.h +4 -2
  94. data/vendor/libgit2/src/cache.c +9 -9
  95. data/vendor/libgit2/src/cache.h +1 -1
  96. data/vendor/libgit2/src/cc-compat.h +2 -0
  97. data/vendor/libgit2/src/checkout.c +263 -82
  98. data/vendor/libgit2/src/checkout.h +1 -0
  99. data/vendor/libgit2/src/cherrypick.c +41 -44
  100. data/vendor/libgit2/src/clone.c +96 -58
  101. data/vendor/libgit2/src/commit.c +5 -31
  102. data/vendor/libgit2/src/commit_list.h +3 -1
  103. data/vendor/libgit2/src/config.c +0 -17
  104. data/vendor/libgit2/src/config_cache.c +0 -2
  105. data/vendor/libgit2/src/config_file.c +12 -15
  106. data/vendor/libgit2/src/crlf.c +2 -1
  107. data/vendor/libgit2/src/describe.c +886 -0
  108. data/vendor/libgit2/src/diff.c +29 -3
  109. data/vendor/libgit2/src/diff_file.c +1 -0
  110. data/vendor/libgit2/src/diff_patch.c +2 -3
  111. data/vendor/libgit2/src/diff_print.c +11 -9
  112. data/vendor/libgit2/src/diff_tform.c +4 -4
  113. data/vendor/libgit2/src/errors.c +9 -7
  114. data/vendor/libgit2/src/fetch.c +6 -6
  115. data/vendor/libgit2/src/fetchhead.h +2 -4
  116. data/vendor/libgit2/src/filebuf.c +0 -2
  117. data/vendor/libgit2/src/filebuf.h +2 -3
  118. data/vendor/libgit2/src/fileops.c +9 -7
  119. data/vendor/libgit2/src/global.c +44 -35
  120. data/vendor/libgit2/src/global.h +2 -0
  121. data/vendor/libgit2/src/graph.c +2 -2
  122. data/vendor/libgit2/src/hash.h +3 -1
  123. data/vendor/libgit2/src/hash/hash_common_crypto.h +44 -0
  124. data/vendor/libgit2/src/hash/hash_win32.c +1 -1
  125. data/vendor/libgit2/src/hashsig.c +1 -1
  126. data/vendor/libgit2/src/ignore.c +5 -88
  127. data/vendor/libgit2/src/index.c +70 -57
  128. data/vendor/libgit2/src/index.h +1 -0
  129. data/vendor/libgit2/src/indexer.c +16 -5
  130. data/vendor/libgit2/src/iterator.c +70 -1
  131. data/vendor/libgit2/src/iterator.h +5 -1
  132. data/vendor/libgit2/src/map.h +0 -1
  133. data/vendor/libgit2/src/merge.c +203 -327
  134. data/vendor/libgit2/src/merge.h +3 -13
  135. data/vendor/libgit2/src/mwindow.c +119 -8
  136. data/vendor/libgit2/src/mwindow.h +9 -1
  137. data/vendor/libgit2/src/netops.c +7 -8
  138. data/vendor/libgit2/src/netops.h +6 -16
  139. data/vendor/libgit2/src/notes.c +31 -4
  140. data/vendor/libgit2/src/notes.h +3 -0
  141. data/vendor/libgit2/src/odb.c +23 -1
  142. data/vendor/libgit2/src/odb_loose.c +1 -1
  143. data/vendor/libgit2/src/odb_pack.c +6 -3
  144. data/vendor/libgit2/src/oid.c +9 -1
  145. data/vendor/libgit2/src/oid.h +11 -0
  146. data/vendor/libgit2/src/oidarray.c +21 -0
  147. data/vendor/libgit2/src/oidarray.h +18 -0
  148. data/vendor/libgit2/src/oidmap.h +16 -0
  149. data/vendor/libgit2/src/pack.c +20 -7
  150. data/vendor/libgit2/src/pack.h +3 -0
  151. data/vendor/libgit2/src/path.c +120 -293
  152. data/vendor/libgit2/src/path.h +21 -44
  153. data/vendor/libgit2/src/pathspec.c +1 -1
  154. data/vendor/libgit2/src/pool.c +5 -11
  155. data/vendor/libgit2/src/pool.h +0 -2
  156. data/vendor/libgit2/src/posix.c +6 -6
  157. data/vendor/libgit2/src/posix.h +48 -28
  158. data/vendor/libgit2/src/push.c +19 -48
  159. data/vendor/libgit2/src/push.h +2 -4
  160. data/vendor/libgit2/src/rebase.c +1125 -0
  161. data/vendor/libgit2/src/refdb.c +19 -0
  162. data/vendor/libgit2/src/refdb.h +2 -1
  163. data/vendor/libgit2/src/refdb_fs.c +101 -29
  164. data/vendor/libgit2/src/reflog.c +1 -1
  165. data/vendor/libgit2/src/refs.c +38 -3
  166. data/vendor/libgit2/src/refs.h +13 -2
  167. data/vendor/libgit2/src/refspec.c +20 -2
  168. data/vendor/libgit2/src/remote.c +288 -154
  169. data/vendor/libgit2/src/remote.h +5 -1
  170. data/vendor/libgit2/src/repository.c +75 -36
  171. data/vendor/libgit2/src/repository.h +3 -25
  172. data/vendor/libgit2/src/reset.c +5 -1
  173. data/vendor/libgit2/src/revert.c +4 -6
  174. data/vendor/libgit2/src/revparse.c +15 -18
  175. data/vendor/libgit2/src/revwalk.c +96 -22
  176. data/vendor/libgit2/src/revwalk.h +5 -4
  177. data/vendor/libgit2/src/settings.c +22 -0
  178. data/vendor/libgit2/src/signature.c +37 -2
  179. data/vendor/libgit2/src/signature.h +3 -0
  180. data/vendor/libgit2/src/stash.c +17 -12
  181. data/vendor/libgit2/src/status.c +13 -3
  182. data/vendor/libgit2/src/strnlen.h +2 -1
  183. data/vendor/libgit2/src/submodule.c +75 -35
  184. data/vendor/libgit2/src/thread-utils.h +4 -9
  185. data/vendor/libgit2/src/trace.h +9 -1
  186. data/vendor/libgit2/src/transaction.c +352 -0
  187. data/vendor/libgit2/src/transport.c +91 -97
  188. data/vendor/libgit2/src/transports/auth.c +71 -0
  189. data/vendor/libgit2/src/transports/auth.h +63 -0
  190. data/vendor/libgit2/src/transports/auth_negotiate.c +275 -0
  191. data/vendor/libgit2/src/transports/auth_negotiate.h +27 -0
  192. data/vendor/libgit2/src/transports/cred.c +58 -0
  193. data/vendor/libgit2/src/transports/cred.h +14 -0
  194. data/vendor/libgit2/src/transports/cred_helpers.c +3 -0
  195. data/vendor/libgit2/src/transports/git.c +1 -0
  196. data/vendor/libgit2/src/transports/http.c +208 -82
  197. data/vendor/libgit2/src/transports/local.c +2 -2
  198. data/vendor/libgit2/src/transports/smart.c +2 -0
  199. data/vendor/libgit2/src/transports/smart.h +2 -0
  200. data/vendor/libgit2/src/transports/smart_protocol.c +10 -10
  201. data/vendor/libgit2/src/transports/ssh.c +243 -57
  202. data/vendor/libgit2/src/transports/winhttp.c +139 -35
  203. data/vendor/libgit2/src/tree-cache.c +118 -31
  204. data/vendor/libgit2/src/tree-cache.h +12 -7
  205. data/vendor/libgit2/src/tree.c +83 -64
  206. data/vendor/libgit2/src/tree.h +2 -3
  207. data/vendor/libgit2/src/unix/map.c +8 -2
  208. data/vendor/libgit2/src/unix/posix.h +23 -9
  209. data/vendor/libgit2/src/unix/realpath.c +8 -7
  210. data/vendor/libgit2/src/userdiff.h +3 -3
  211. data/vendor/libgit2/src/util.c +2 -92
  212. data/vendor/libgit2/src/util.h +3 -15
  213. data/vendor/libgit2/src/win32/findfile.c +0 -1
  214. data/vendor/libgit2/src/win32/map.c +3 -2
  215. data/vendor/libgit2/src/win32/mingw-compat.h +5 -12
  216. data/vendor/libgit2/src/win32/msvc-compat.h +3 -32
  217. data/vendor/libgit2/src/win32/posix.h +20 -32
  218. data/vendor/libgit2/src/win32/posix_w32.c +103 -31
  219. data/vendor/libgit2/src/win32/utf-conv.c +6 -36
  220. data/vendor/libgit2/src/win32/utf-conv.h +39 -0
  221. data/vendor/libgit2/src/win32/w32_util.h +0 -1
  222. metadata +32 -7
  223. data/vendor/libgit2/src/win32/path_w32.c +0 -305
  224. data/vendor/libgit2/src/win32/path_w32.h +0 -82
@@ -210,7 +210,7 @@ static int packfile_load__cb(void *data, git_buf *path)
210
210
  return 0;
211
211
  }
212
212
 
213
- error = git_packfile_alloc(&pack, path->ptr);
213
+ error = git_mwindow_get_pack(&pack, path->ptr);
214
214
 
215
215
  /* ignore missing .pack file as git does */
216
216
  if (error == GIT_ENOTFOUND) {
@@ -605,7 +605,7 @@ static void pack_backend__free(git_odb_backend *_backend)
605
605
 
606
606
  for (i = 0; i < backend->packs.length; ++i) {
607
607
  struct git_pack_file *p = git_vector_get(&backend->packs, i);
608
- git_packfile_free(p);
608
+ git_mwindow_put_pack(p);
609
609
  }
610
610
 
611
611
  git_vector_free(&backend->packs);
@@ -647,7 +647,7 @@ int git_odb_backend_one_pack(git_odb_backend **backend_out, const char *idx)
647
647
  if (pack_backend__alloc(&backend, 1) < 0)
648
648
  return -1;
649
649
 
650
- if (git_packfile_alloc(&packfile, idx) < 0 ||
650
+ if (git_mwindow_get_pack(&packfile, idx) < 0 ||
651
651
  git_vector_insert(&backend->packs, packfile) < 0)
652
652
  {
653
653
  pack_backend__free((git_odb_backend *)backend);
@@ -664,6 +664,9 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
664
664
  struct pack_backend *backend = NULL;
665
665
  git_buf path = GIT_BUF_INIT;
666
666
 
667
+ if (git_mwindow_files_init() < 0)
668
+ return -1;
669
+
667
670
  if (pack_backend__alloc(&backend, 8) < 0)
668
671
  return -1;
669
672
 
@@ -8,6 +8,7 @@
8
8
  #include "common.h"
9
9
  #include "git2/oid.h"
10
10
  #include "repository.h"
11
+ #include "global.h"
11
12
  #include <string.h>
12
13
  #include <limits.h>
13
14
 
@@ -99,6 +100,13 @@ void git_oid_pathfmt(char *str, const git_oid *oid)
99
100
  str = fmt_one(str, oid->id[i]);
100
101
  }
101
102
 
103
+ char *git_oid_tostr_s(const git_oid *oid)
104
+ {
105
+ char *str = GIT_GLOBAL->oid_fmt;
106
+ git_oid_nfmt(str, GIT_OID_HEXSZ + 1, oid);
107
+ return str;
108
+ }
109
+
102
110
  char *git_oid_allocfmt(const git_oid *oid)
103
111
  {
104
112
  char *str = git__malloc(GIT_OID_HEXSZ + 1);
@@ -203,7 +211,7 @@ int git_oid_ncmp(const git_oid *oid_a, const git_oid *oid_b, size_t len)
203
211
 
204
212
  int git_oid_strcmp(const git_oid *oid_a, const char *str)
205
213
  {
206
- const unsigned char *a = oid_a->id;
214
+ const unsigned char *a;
207
215
  unsigned char strval;
208
216
  int hexval;
209
217
 
@@ -9,6 +9,17 @@
9
9
 
10
10
  #include "git2/oid.h"
11
11
 
12
+ /**
13
+ * Format a git_oid into a newly allocated c-string.
14
+ *
15
+ * The c-string is owned by the caller and needs to be manually freed.
16
+ *
17
+ * @param id the oid structure to format
18
+ * @return the c-string; NULL if memory is exhausted. Caller must
19
+ * deallocate the string with git__free().
20
+ */
21
+ char *git_oid_allocfmt(const git_oid *id);
22
+
12
23
  GIT_INLINE(int) git_oid__hashcmp(const unsigned char *sha1, const unsigned char *sha2)
13
24
  {
14
25
  int i;
@@ -0,0 +1,21 @@
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 "git2/oidarray.h"
9
+ #include "oidarray.h"
10
+ #include "array.h"
11
+
12
+ void git_oidarray_free(git_oidarray *arr)
13
+ {
14
+ git__free(arr->ids);
15
+ }
16
+
17
+ void git_oidarray__from_array(git_oidarray *arr, git_array_oid_t *array)
18
+ {
19
+ arr->count = array->size;
20
+ arr->ids = array->ptr;
21
+ }
@@ -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_oidarray_h__
8
+ #define INCLUDE_oidarray_h__
9
+
10
+ #include "common.h"
11
+ #include "git2/oidarray.h"
12
+ #include "array.h"
13
+
14
+ typedef git_array_t(git_oid) git_array_oid_t;
15
+
16
+ extern void git_oidarray__from_array(git_oidarray *arr, git_array_oid_t *array);
17
+
18
+ #endif
@@ -32,4 +32,20 @@ GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid)
32
32
  #define git_oidmap_alloc() kh_init(oid)
33
33
  #define git_oidmap_free(h) kh_destroy(oid,h), h = NULL
34
34
 
35
+ #define git_oidmap_lookup_index(h, k) kh_get(oid, h, k)
36
+ #define git_oidmap_valid_index(h, idx) (idx != kh_end(h))
37
+
38
+ #define git_oidmap_value_at(h, idx) kh_val(h, idx)
39
+
40
+ #define git_oidmap_insert(h, key, val, rval) do { \
41
+ khiter_t __pos = kh_put(oid, h, key, &rval); \
42
+ if (rval >= 0) { \
43
+ if (rval == 0) kh_key(h, __pos) = key; \
44
+ kh_val(h, __pos) = val; \
45
+ } } while (0)
46
+
47
+ #define git_oidmap_foreach_value kh_foreach_value
48
+
49
+ #define git_oidmap_size(h) kh_size(h)
50
+
35
51
  #endif
@@ -648,9 +648,6 @@ int git_packfile_unpack(
648
648
  base_type = elem->type;
649
649
  }
650
650
 
651
- if (error < 0)
652
- goto cleanup;
653
-
654
651
  switch (base_type) {
655
652
  case GIT_OBJ_COMMIT:
656
653
  case GIT_OBJ_TREE:
@@ -968,10 +965,10 @@ void git_packfile_free(struct git_pack_file *p)
968
965
 
969
966
  cache_free(&p->bases);
970
967
 
971
- git_mwindow_free_all(&p->mwf);
972
-
973
- if (p->mwf.fd >= 0)
968
+ if (p->mwf.fd >= 0) {
969
+ git_mwindow_free_all_locked(&p->mwf);
974
970
  p_close(p->mwf.fd);
971
+ }
975
972
 
976
973
  pack_index_free(p);
977
974
 
@@ -1063,6 +1060,23 @@ cleanup:
1063
1060
  return -1;
1064
1061
  }
1065
1062
 
1063
+ int git_packfile__name(char **out, const char *path)
1064
+ {
1065
+ size_t path_len;
1066
+ git_buf buf = GIT_BUF_INIT;
1067
+
1068
+ path_len = strlen(path);
1069
+
1070
+ if (path_len < strlen(".idx"))
1071
+ return git_odb__error_notfound("invalid packfile path", NULL);
1072
+
1073
+ if (git_buf_printf(&buf, "%.*s.pack", (int)(path_len - strlen(".idx")), path) < 0)
1074
+ return -1;
1075
+
1076
+ *out = git_buf_detach(&buf);
1077
+ return 0;
1078
+ }
1079
+
1066
1080
  int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
1067
1081
  {
1068
1082
  struct stat st;
@@ -1091,7 +1105,6 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
1091
1105
  p->pack_keep = 1;
1092
1106
 
1093
1107
  memcpy(p->pack_name + root_len, ".pack", sizeof(".pack"));
1094
- path_len = path_len - strlen(".idx") + strlen(".pack");
1095
1108
  }
1096
1109
 
1097
1110
  if (p_stat(p->pack_name, &st) < 0 || !S_ISREG(st.st_mode)) {
@@ -90,6 +90,7 @@ struct git_pack_file {
90
90
  git_mwindow_file mwf;
91
91
  git_map index_map;
92
92
  git_mutex lock; /* protect updates to mwf and index_map */
93
+ git_atomic refcount;
93
94
 
94
95
  uint32_t num_objects;
95
96
  uint32_t num_bad_objects;
@@ -123,6 +124,8 @@ typedef struct git_packfile_stream {
123
124
 
124
125
  size_t git_packfile__object_header(unsigned char *hdr, size_t size, git_otype type);
125
126
 
127
+ int git_packfile__name(char **out, const char *path);
128
+
126
129
  int git_packfile_unpack_header(
127
130
  size_t *size_p,
128
131
  git_otype *type_p,
@@ -7,7 +7,6 @@
7
7
  #include "common.h"
8
8
  #include "path.h"
9
9
  #include "posix.h"
10
- #include "repository.h"
11
10
  #ifdef GIT_WIN32
12
11
  #include "win32/posix.h"
13
12
  #include "win32/w32_util.h"
@@ -378,26 +377,33 @@ static int error_invalid_local_file_uri(const char *uri)
378
377
  return -1;
379
378
  }
380
379
 
381
- int git_path_fromurl(git_buf *local_path_out, const char *file_url)
380
+ static int local_file_url_prefixlen(const char *file_url)
382
381
  {
383
- int offset = 0, len;
382
+ int len = -1;
384
383
 
385
- assert(local_path_out && file_url);
384
+ if (git__prefixcmp(file_url, "file://") == 0) {
385
+ if (file_url[7] == '/')
386
+ len = 8;
387
+ else if (git__prefixcmp(file_url + 7, "localhost/") == 0)
388
+ len = 17;
389
+ }
386
390
 
387
- if (git__prefixcmp(file_url, "file://") != 0)
388
- return error_invalid_local_file_uri(file_url);
391
+ return len;
392
+ }
389
393
 
390
- offset += 7;
391
- len = (int)strlen(file_url);
394
+ bool git_path_is_local_file_url(const char *file_url)
395
+ {
396
+ return (local_file_url_prefixlen(file_url) > 0);
397
+ }
392
398
 
393
- if (offset < len && file_url[offset] == '/')
394
- offset++;
395
- else if (offset < len && git__prefixcmp(file_url + offset, "localhost/") == 0)
396
- offset += 10;
397
- else
398
- return error_invalid_local_file_uri(file_url);
399
+ int git_path_fromurl(git_buf *local_path_out, const char *file_url)
400
+ {
401
+ int offset;
402
+
403
+ assert(local_path_out && file_url);
399
404
 
400
- if (offset >= len || file_url[offset] == '/')
405
+ if ((offset = local_file_url_prefixlen(file_url)) < 0 ||
406
+ file_url[offset] == '\0' || file_url[offset] == '/')
401
407
  return error_invalid_local_file_uri(file_url);
402
408
 
403
409
  #ifndef GIT_WIN32
@@ -405,14 +411,13 @@ int git_path_fromurl(git_buf *local_path_out, const char *file_url)
405
411
  #endif
406
412
 
407
413
  git_buf_clear(local_path_out);
408
-
409
414
  return git__percent_decode(local_path_out, file_url + offset);
410
415
  }
411
416
 
412
417
  int git_path_walk_up(
413
418
  git_buf *path,
414
419
  const char *ceiling,
415
- int (*cb)(void *data, git_buf *),
420
+ int (*cb)(void *data, const char *),
416
421
  void *data)
417
422
  {
418
423
  int error = 0;
@@ -430,12 +435,20 @@ int git_path_walk_up(
430
435
  }
431
436
  scan = git_buf_len(path);
432
437
 
438
+ /* empty path: yield only once */
439
+ if (!scan) {
440
+ error = cb(data, "");
441
+ if (error)
442
+ giterr_set_after_callback(error);
443
+ return error;
444
+ }
445
+
433
446
  iter.ptr = path->ptr;
434
447
  iter.size = git_buf_len(path);
435
448
  iter.asize = path->asize;
436
449
 
437
450
  while (scan >= stop) {
438
- error = cb(data, &iter);
451
+ error = cb(data, iter.ptr);
439
452
  iter.ptr[scan] = oldc;
440
453
 
441
454
  if (error) {
@@ -455,6 +468,13 @@ int git_path_walk_up(
455
468
  if (scan >= 0)
456
469
  iter.ptr[scan] = oldc;
457
470
 
471
+ /* relative path: yield for the last component */
472
+ if (!error && stop == 0 && iter.ptr[0] != '/') {
473
+ error = cb(data, "");
474
+ if (error)
475
+ giterr_set_after_callback(error);
476
+ }
477
+
458
478
  return error;
459
479
  }
460
480
 
@@ -755,6 +775,64 @@ int git_path_cmp(
755
775
  return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;
756
776
  }
757
777
 
778
+ int git_path_make_relative(git_buf *path, const char *parent)
779
+ {
780
+ const char *p, *q, *p_dirsep, *q_dirsep;
781
+ size_t plen = path->size, newlen, depth = 1, i, offset;
782
+
783
+ for (p_dirsep = p = path->ptr, q_dirsep = q = parent; *p && *q; p++, q++) {
784
+ if (*p == '/' && *q == '/') {
785
+ p_dirsep = p;
786
+ q_dirsep = q;
787
+ }
788
+ else if (*p != *q)
789
+ break;
790
+ }
791
+
792
+ /* need at least 1 common path segment */
793
+ if ((p_dirsep == path->ptr || q_dirsep == parent) &&
794
+ (*p_dirsep != '/' || *q_dirsep != '/')) {
795
+ giterr_set(GITERR_INVALID,
796
+ "%s is not a parent of %s", parent, path->ptr);
797
+ return GIT_ENOTFOUND;
798
+ }
799
+
800
+ if (*p == '/' && !*q)
801
+ p++;
802
+ else if (!*p && *q == '/')
803
+ q++;
804
+ else if (!*p && !*q)
805
+ return git_buf_clear(path), 0;
806
+ else {
807
+ p = p_dirsep + 1;
808
+ q = q_dirsep + 1;
809
+ }
810
+
811
+ plen -= (p - path->ptr);
812
+
813
+ if (!*q)
814
+ return git_buf_set(path, p, plen);
815
+
816
+ for (; (q = strchr(q, '/')) && *(q + 1); q++)
817
+ depth++;
818
+
819
+ newlen = (depth * 3) + plen;
820
+
821
+ /* save the offset as we might realllocate the pointer */
822
+ offset = p - path->ptr;
823
+ if (git_buf_try_grow(path, newlen + 1, 1, 0) < 0)
824
+ return -1;
825
+ p = path->ptr + offset;
826
+
827
+ memmove(path->ptr + (depth * 3), p, plen + 1);
828
+
829
+ for (i = 0; i < depth; i++)
830
+ memcpy(path->ptr + (i * 3), "../", 3);
831
+
832
+ path->size = newlen;
833
+ return 0;
834
+ }
835
+
758
836
  bool git_path_has_non_ascii(const char *path, size_t pathlen)
759
837
  {
760
838
  const uint8_t *scan = (const uint8_t *)path, *end;
@@ -915,7 +993,7 @@ int git_path_direach(
915
993
  path_dirent_data de_data;
916
994
  struct dirent *de, *de_buf = (struct dirent *)&de_data;
917
995
 
918
- (void)flags;
996
+ GIT_UNUSED(flags);
919
997
 
920
998
  #ifdef GIT_USE_ICONV
921
999
  git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
@@ -986,7 +1064,7 @@ int git_path_dirload(
986
1064
  path_dirent_data de_data;
987
1065
  struct dirent *de, *de_buf = (struct dirent *)&de_data;
988
1066
 
989
- (void)flags;
1067
+ GIT_UNUSED(flags);
990
1068
 
991
1069
  #ifdef GIT_USE_ICONV
992
1070
  git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
@@ -1038,8 +1116,10 @@ int git_path_dirload(
1038
1116
  entry_path[path_len] = '/';
1039
1117
  memcpy(&entry_path[path_len + need_slash], de_path, de_len);
1040
1118
 
1041
- if ((error = git_vector_insert(contents, entry_path)) < 0)
1119
+ if ((error = git_vector_insert(contents, entry_path)) < 0) {
1120
+ git__free(entry_path);
1042
1121
  break;
1122
+ }
1043
1123
  }
1044
1124
 
1045
1125
  closedir(dir);
@@ -1115,20 +1195,32 @@ int git_path_dirload_with_stat(
1115
1195
 
1116
1196
  if ((error = git_buf_joinpath(&full, full.ptr, ps->path)) < 0 ||
1117
1197
  (error = git_path_lstat(full.ptr, &ps->st)) < 0) {
1198
+
1118
1199
  if (error == GIT_ENOTFOUND) {
1119
- giterr_clear();
1120
- error = 0;
1200
+ /* file was removed between readdir and lstat */
1201
+ char *entry_path = git_vector_get(contents, i);
1121
1202
  git_vector_remove(contents, i--);
1122
- continue;
1203
+ git__free(entry_path);
1204
+ } else {
1205
+ /* Treat the file as unreadable if we get any other error */
1206
+ memset(&ps->st, 0, sizeof(ps->st));
1207
+ ps->st.st_mode = GIT_FILEMODE_UNREADABLE;
1123
1208
  }
1124
1209
 
1125
- break;
1210
+ giterr_clear();
1211
+ error = 0;
1212
+ continue;
1126
1213
  }
1127
1214
 
1128
1215
  if (S_ISDIR(ps->st.st_mode)) {
1129
1216
  ps->path[ps->path_len++] = '/';
1130
1217
  ps->path[ps->path_len] = '\0';
1131
1218
  }
1219
+ else if (!S_ISREG(ps->st.st_mode) && !S_ISLNK(ps->st.st_mode)) {
1220
+ char *entry_path = git_vector_get(contents, i);
1221
+ git_vector_remove(contents, i--);
1222
+ git__free(entry_path);
1223
+ }
1132
1224
  }
1133
1225
 
1134
1226
  /* sort now that directory suffix is added */
@@ -1141,273 +1233,8 @@ int git_path_dirload_with_stat(
1141
1233
 
1142
1234
  int git_path_from_url_or_path(git_buf *local_path_out, const char *url_or_path)
1143
1235
  {
1144
- int error;
1145
-
1146
- /* If url_or_path begins with file:// treat it as a URL */
1147
- if (!git__prefixcmp(url_or_path, "file://")) {
1148
- if ((error = git_path_fromurl(local_path_out, url_or_path)) < 0) {
1149
- return error;
1150
- }
1151
- } else { /* We assume url_or_path is already a path */
1152
- if ((error = git_buf_sets(local_path_out, url_or_path)) < 0) {
1153
- return error;
1154
- }
1155
- }
1156
-
1157
- return 0;
1158
- }
1159
-
1160
- /* Reject paths like AUX or COM1, or those versions that end in a dot or
1161
- * colon. ("AUX." or "AUX:")
1162
- */
1163
- GIT_INLINE(bool) verify_dospath(
1164
- const char *component,
1165
- size_t len,
1166
- const char dospath[3],
1167
- bool trailing_num)
1168
- {
1169
- size_t last = trailing_num ? 4 : 3;
1170
-
1171
- if (len < last || git__strncasecmp(component, dospath, 3) != 0)
1172
- return true;
1173
-
1174
- if (trailing_num && !git__isdigit(component[3]))
1175
- return true;
1176
-
1177
- return (len > last &&
1178
- component[last] != '.' &&
1179
- component[last] != ':');
1180
- }
1181
-
1182
- static int32_t next_hfs_char(const char **in, size_t *len)
1183
- {
1184
- while (*len) {
1185
- int32_t codepoint;
1186
- int cp_len = git__utf8_iterate((const uint8_t *)(*in), (int)(*len), &codepoint);
1187
- if (cp_len < 0)
1188
- return -1;
1189
-
1190
- (*in) += cp_len;
1191
- (*len) -= cp_len;
1192
-
1193
- /* these code points are ignored completely */
1194
- switch (codepoint) {
1195
- case 0x200c: /* ZERO WIDTH NON-JOINER */
1196
- case 0x200d: /* ZERO WIDTH JOINER */
1197
- case 0x200e: /* LEFT-TO-RIGHT MARK */
1198
- case 0x200f: /* RIGHT-TO-LEFT MARK */
1199
- case 0x202a: /* LEFT-TO-RIGHT EMBEDDING */
1200
- case 0x202b: /* RIGHT-TO-LEFT EMBEDDING */
1201
- case 0x202c: /* POP DIRECTIONAL FORMATTING */
1202
- case 0x202d: /* LEFT-TO-RIGHT OVERRIDE */
1203
- case 0x202e: /* RIGHT-TO-LEFT OVERRIDE */
1204
- case 0x206a: /* INHIBIT SYMMETRIC SWAPPING */
1205
- case 0x206b: /* ACTIVATE SYMMETRIC SWAPPING */
1206
- case 0x206c: /* INHIBIT ARABIC FORM SHAPING */
1207
- case 0x206d: /* ACTIVATE ARABIC FORM SHAPING */
1208
- case 0x206e: /* NATIONAL DIGIT SHAPES */
1209
- case 0x206f: /* NOMINAL DIGIT SHAPES */
1210
- case 0xfeff: /* ZERO WIDTH NO-BREAK SPACE */
1211
- continue;
1212
- }
1213
-
1214
- /* fold into lowercase -- this will only fold characters in
1215
- * the ASCII range, which is perfectly fine, because the
1216
- * git folder name can only be composed of ascii characters
1217
- */
1218
- return tolower(codepoint);
1219
- }
1220
- return 0; /* NULL byte -- end of string */
1221
- }
1222
-
1223
- static bool verify_dotgit_hfs(const char *path, size_t len)
1224
- {
1225
- if (next_hfs_char(&path, &len) != '.' ||
1226
- next_hfs_char(&path, &len) != 'g' ||
1227
- next_hfs_char(&path, &len) != 'i' ||
1228
- next_hfs_char(&path, &len) != 't' ||
1229
- next_hfs_char(&path, &len) != 0)
1230
- return true;
1231
-
1232
- return false;
1233
- }
1234
-
1235
- GIT_INLINE(bool) verify_dotgit_ntfs(git_repository *repo, const char *path, size_t len)
1236
- {
1237
- const char *shortname = NULL;
1238
- size_t i, start, shortname_len = 0;
1239
-
1240
- /* See if the repo has a custom shortname (not "GIT~1") */
1241
- if (repo &&
1242
- (shortname = git_repository__8dot3_name(repo)) &&
1243
- shortname != git_repository__8dot3_default)
1244
- shortname_len = strlen(shortname);
1245
-
1246
- if (len >= 4 && strncasecmp(path, ".git", 4) == 0)
1247
- start = 4;
1248
- else if (len >= git_repository__8dot3_default_len &&
1249
- strncasecmp(path, git_repository__8dot3_default, git_repository__8dot3_default_len) == 0)
1250
- start = git_repository__8dot3_default_len;
1251
- else if (shortname_len && len >= shortname_len &&
1252
- strncasecmp(path, shortname, shortname_len) == 0)
1253
- start = shortname_len;
1236
+ if (git_path_is_local_file_url(url_or_path))
1237
+ return git_path_fromurl(local_path_out, url_or_path);
1254
1238
  else
1255
- return true;
1256
-
1257
- /* Reject paths beginning with ".git\" */
1258
- if (path[start] == '\\')
1259
- return false;
1260
-
1261
- for (i = start; i < len; i++) {
1262
- if (path[i] != ' ' && path[i] != '.')
1263
- return true;
1264
- }
1265
-
1266
- return false;
1267
- }
1268
-
1269
- GIT_INLINE(bool) verify_char(unsigned char c, unsigned int flags)
1270
- {
1271
- if ((flags & GIT_PATH_REJECT_BACKSLASH) && c == '\\')
1272
- return false;
1273
-
1274
- if ((flags & GIT_PATH_REJECT_SLASH) && c == '/')
1275
- return false;
1276
-
1277
- if (flags & GIT_PATH_REJECT_NT_CHARS) {
1278
- if (c < 32)
1279
- return false;
1280
-
1281
- switch (c) {
1282
- case '<':
1283
- case '>':
1284
- case ':':
1285
- case '"':
1286
- case '|':
1287
- case '?':
1288
- case '*':
1289
- return false;
1290
- }
1291
- }
1292
-
1293
- return true;
1294
- }
1295
-
1296
- /*
1297
- * We fundamentally don't like some paths when dealing with user-inputted
1298
- * strings (in checkout or ref names): we don't want dot or dot-dot
1299
- * anywhere, we want to avoid writing weird paths on Windows that can't
1300
- * be handled by tools that use the non-\\?\ APIs, we don't want slashes
1301
- * or double slashes at the end of paths that can make them ambiguous.
1302
- *
1303
- * For checkout, we don't want to recurse into ".git" either.
1304
- */
1305
- static bool verify_component(
1306
- git_repository *repo,
1307
- const char *component,
1308
- size_t len,
1309
- unsigned int flags)
1310
- {
1311
- if (len == 0)
1312
- return false;
1313
-
1314
- if ((flags & GIT_PATH_REJECT_TRAVERSAL) &&
1315
- len == 1 && component[0] == '.')
1316
- return false;
1317
-
1318
- if ((flags & GIT_PATH_REJECT_TRAVERSAL) &&
1319
- len == 2 && component[0] == '.' && component[1] == '.')
1320
- return false;
1321
-
1322
- if ((flags & GIT_PATH_REJECT_TRAILING_DOT) && component[len-1] == '.')
1323
- return false;
1324
-
1325
- if ((flags & GIT_PATH_REJECT_TRAILING_SPACE) && component[len-1] == ' ')
1326
- return false;
1327
-
1328
- if ((flags & GIT_PATH_REJECT_TRAILING_COLON) && component[len-1] == ':')
1329
- return false;
1330
-
1331
- if (flags & GIT_PATH_REJECT_DOS_PATHS) {
1332
- if (!verify_dospath(component, len, "CON", false) ||
1333
- !verify_dospath(component, len, "PRN", false) ||
1334
- !verify_dospath(component, len, "AUX", false) ||
1335
- !verify_dospath(component, len, "NUL", false) ||
1336
- !verify_dospath(component, len, "COM", true) ||
1337
- !verify_dospath(component, len, "LPT", true))
1338
- return false;
1339
- }
1340
-
1341
- if (flags & GIT_PATH_REJECT_DOT_GIT_HFS &&
1342
- !verify_dotgit_hfs(component, len))
1343
- return false;
1344
-
1345
- if (flags & GIT_PATH_REJECT_DOT_GIT_NTFS &&
1346
- !verify_dotgit_ntfs(repo, component, len))
1347
- return false;
1348
-
1349
- if ((flags & GIT_PATH_REJECT_DOT_GIT_HFS) == 0 &&
1350
- (flags & GIT_PATH_REJECT_DOT_GIT_NTFS) == 0 &&
1351
- (flags & GIT_PATH_REJECT_DOT_GIT) &&
1352
- len == 4 &&
1353
- component[0] == '.' &&
1354
- (component[1] == 'g' || component[1] == 'G') &&
1355
- (component[2] == 'i' || component[2] == 'I') &&
1356
- (component[3] == 't' || component[3] == 'T'))
1357
- return false;
1358
-
1359
- return true;
1360
- }
1361
-
1362
- GIT_INLINE(unsigned int) dotgit_flags(
1363
- git_repository *repo,
1364
- unsigned int flags)
1365
- {
1366
- int protectHFS = 0, protectNTFS = 0;
1367
-
1368
- #ifdef __APPLE__
1369
- protectHFS = 1;
1370
- #endif
1371
-
1372
- #ifdef GIT_WIN32
1373
- protectNTFS = 1;
1374
- #endif
1375
-
1376
- if (repo && !protectHFS)
1377
- git_repository__cvar(&protectHFS, repo, GIT_CVAR_PROTECTHFS);
1378
- if (protectHFS)
1379
- flags |= GIT_PATH_REJECT_DOT_GIT_HFS;
1380
-
1381
- if (repo && !protectNTFS)
1382
- git_repository__cvar(&protectNTFS, repo, GIT_CVAR_PROTECTNTFS);
1383
- if (protectNTFS)
1384
- flags |= GIT_PATH_REJECT_DOT_GIT_NTFS;
1385
-
1386
- return flags;
1387
- }
1388
-
1389
- bool git_path_isvalid(
1390
- git_repository *repo,
1391
- const char *path,
1392
- unsigned int flags)
1393
- {
1394
- const char *start, *c;
1395
-
1396
- /* Upgrade the ".git" checks based on platform */
1397
- if ((flags & GIT_PATH_REJECT_DOT_GIT))
1398
- flags = dotgit_flags(repo, flags);
1399
-
1400
- for (start = c = path; *c; c++) {
1401
- if (!verify_char(*c, flags))
1402
- return false;
1403
-
1404
- if (*c == '/') {
1405
- if (!verify_component(repo, start, (c - start), flags))
1406
- return false;
1407
-
1408
- start = c+1;
1409
- }
1410
- }
1411
-
1412
- return verify_component(repo, start, (c - start), flags);
1239
+ return git_buf_sets(local_path_out, url_or_path);
1413
1240
  }