rugged 0.18.0.gh.de28323 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (283) hide show
  1. data/README.md +9 -4
  2. data/Rakefile +1 -1
  3. data/ext/rugged/extconf.rb +10 -0
  4. data/ext/rugged/rugged.c +153 -86
  5. data/ext/rugged/rugged.h +44 -33
  6. data/ext/rugged/rugged_blob.c +288 -60
  7. data/ext/rugged/rugged_branch.c +82 -57
  8. data/ext/rugged/rugged_commit.c +83 -86
  9. data/ext/rugged/rugged_config.c +68 -68
  10. data/ext/rugged/rugged_diff.c +509 -0
  11. data/ext/rugged/rugged_diff_delta.c +94 -0
  12. data/ext/rugged/rugged_diff_hunk.c +100 -0
  13. data/ext/rugged/rugged_diff_line.c +79 -0
  14. data/ext/rugged/rugged_diff_patch.c +169 -0
  15. data/ext/rugged/rugged_index.c +539 -8
  16. data/ext/rugged/rugged_note.c +74 -80
  17. data/ext/rugged/rugged_object.c +63 -8
  18. data/ext/rugged/rugged_reference.c +231 -145
  19. data/ext/rugged/rugged_remote.c +509 -53
  20. data/ext/rugged/rugged_repo.c +572 -236
  21. data/ext/rugged/rugged_revwalk.c +59 -36
  22. data/ext/rugged/rugged_settings.c +7 -9
  23. data/ext/rugged/rugged_signature.c +7 -11
  24. data/ext/rugged/rugged_tag.c +93 -39
  25. data/ext/rugged/rugged_tree.c +321 -58
  26. data/lib/rugged.rb +1 -0
  27. data/lib/rugged/commit.rb +16 -1
  28. data/lib/rugged/console.rb +9 -0
  29. data/lib/rugged/diff.rb +19 -0
  30. data/lib/rugged/diff/delta.rb +54 -0
  31. data/lib/rugged/diff/hunk.rb +23 -0
  32. data/lib/rugged/diff/line.rb +29 -0
  33. data/lib/rugged/diff/patch.rb +28 -0
  34. data/lib/rugged/repository.rb +36 -39
  35. data/lib/rugged/version.rb +1 -1
  36. data/test/blob_test.rb +308 -1
  37. data/test/branch_test.rb +7 -0
  38. data/test/commit_test.rb +7 -10
  39. data/test/coverage/cover.rb +9 -1
  40. data/test/diff_test.rb +777 -0
  41. data/test/fixtures/archive.tar.gz +0 -0
  42. data/test/fixtures/attr/attr0 +1 -0
  43. data/test/fixtures/attr/attr1 +29 -0
  44. data/test/fixtures/attr/attr2 +21 -0
  45. data/test/fixtures/attr/attr3 +4 -0
  46. data/test/fixtures/attr/binfile +1 -0
  47. data/test/fixtures/attr/dir/file +0 -0
  48. data/test/fixtures/attr/file +1 -0
  49. data/test/fixtures/attr/gitattributes +29 -0
  50. data/test/fixtures/attr/gitignore +2 -0
  51. data/test/fixtures/attr/ign +1 -0
  52. data/test/fixtures/attr/macro_bad +1 -0
  53. data/test/fixtures/attr/macro_test +1 -0
  54. data/test/fixtures/attr/root_test1 +1 -0
  55. data/test/fixtures/attr/root_test2 +6 -0
  56. data/test/fixtures/attr/root_test3 +19 -0
  57. data/test/fixtures/attr/root_test4.txt +14 -0
  58. data/test/fixtures/attr/sub/abc +37 -0
  59. data/test/fixtures/attr/sub/dir/file +0 -0
  60. data/test/fixtures/attr/sub/file +1 -0
  61. data/test/fixtures/attr/sub/ign/file +1 -0
  62. data/test/fixtures/attr/sub/ign/sub/file +1 -0
  63. data/test/fixtures/attr/sub/sub/dir +0 -0
  64. data/test/fixtures/attr/sub/sub/file +1 -0
  65. data/test/fixtures/attr/sub/sub/subsub.txt +1 -0
  66. data/test/fixtures/attr/sub/subdir_test1 +2 -0
  67. data/test/fixtures/attr/sub/subdir_test2.txt +1 -0
  68. data/test/fixtures/diff/another.txt +38 -0
  69. data/test/fixtures/diff/readme.txt +36 -0
  70. data/test/fixtures/mergedrepo/conflicts-one.txt +5 -0
  71. data/test/fixtures/mergedrepo/conflicts-two.txt +5 -0
  72. data/test/fixtures/mergedrepo/one.txt +10 -0
  73. data/test/fixtures/mergedrepo/two.txt +12 -0
  74. data/test/fixtures/status/current_file +1 -0
  75. data/test/fixtures/status/ignored_file +1 -0
  76. data/test/fixtures/status/modified_file +2 -0
  77. data/test/fixtures/status/new_file +1 -0
  78. data/test/fixtures/status/staged_changes +2 -0
  79. data/test/fixtures/status/staged_changes_modified_file +3 -0
  80. data/test/fixtures/status/staged_delete_modified_file +1 -0
  81. data/test/fixtures/status/staged_new_file +1 -0
  82. data/test/fixtures/status/staged_new_file_modified_file +2 -0
  83. data/test/fixtures/status/subdir.txt +2 -0
  84. data/test/fixtures/status/subdir/current_file +1 -0
  85. data/test/fixtures/status/subdir/modified_file +2 -0
  86. data/test/fixtures/status/subdir/new_file +1 -0
  87. data/test/fixtures/status//350/277/231 +1 -0
  88. data/test/fixtures/testrepo.git/config +5 -0
  89. data/test/fixtures/testrepo.git/objects/77/71329dfa3002caf8c61a0ceb62a31d09023f37 +0 -0
  90. data/test/fixtures/text_file.md +464 -0
  91. data/test/fixtures/unsymlinked.git/HEAD +1 -0
  92. data/test/fixtures/unsymlinked.git/config +6 -0
  93. data/test/fixtures/unsymlinked.git/description +1 -0
  94. data/test/fixtures/unsymlinked.git/info/exclude +2 -0
  95. data/test/fixtures/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf +0 -0
  96. data/test/fixtures/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b +0 -0
  97. data/test/fixtures/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c +0 -0
  98. data/test/fixtures/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 +0 -0
  99. data/test/fixtures/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c +0 -0
  100. data/test/fixtures/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 +0 -0
  101. data/test/fixtures/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d +0 -0
  102. data/test/fixtures/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 +0 -0
  103. data/test/fixtures/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 +0 -0
  104. data/test/fixtures/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 +2 -0
  105. data/test/fixtures/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 +0 -0
  106. data/test/fixtures/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a +0 -0
  107. data/test/fixtures/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 +0 -0
  108. data/test/fixtures/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 +0 -0
  109. data/test/fixtures/unsymlinked.git/refs/heads/exe-file +1 -0
  110. data/test/fixtures/unsymlinked.git/refs/heads/master +1 -0
  111. data/test/fixtures/unsymlinked.git/refs/heads/reg-file +1 -0
  112. data/test/index_test.rb +120 -0
  113. data/test/reference_test.rb +38 -3
  114. data/test/remote_test.rb +224 -3
  115. data/test/repo_reset_test.rb +2 -0
  116. data/test/repo_test.rb +147 -10
  117. data/test/test_helper.rb +5 -2
  118. data/vendor/libgit2/include/git2/attr.h +3 -3
  119. data/vendor/libgit2/include/git2/blob.h +11 -17
  120. data/vendor/libgit2/include/git2/branch.h +3 -2
  121. data/vendor/libgit2/include/git2/checkout.h +7 -0
  122. data/vendor/libgit2/include/git2/clone.h +3 -0
  123. data/vendor/libgit2/include/git2/commit.h +61 -66
  124. data/vendor/libgit2/include/git2/common.h +73 -42
  125. data/vendor/libgit2/include/git2/config.h +57 -71
  126. data/vendor/libgit2/include/git2/cred_helpers.h +2 -2
  127. data/vendor/libgit2/include/git2/diff.h +179 -30
  128. data/vendor/libgit2/include/git2/errors.h +3 -3
  129. data/vendor/libgit2/include/git2/index.h +225 -146
  130. data/vendor/libgit2/include/git2/indexer.h +2 -22
  131. data/vendor/libgit2/include/git2/inttypes.h +9 -9
  132. data/vendor/libgit2/include/git2/merge.h +123 -5
  133. data/vendor/libgit2/include/git2/odb.h +59 -38
  134. data/vendor/libgit2/include/git2/odb_backend.h +45 -104
  135. data/vendor/libgit2/include/git2/oid.h +30 -19
  136. data/vendor/libgit2/include/git2/pack.h +21 -3
  137. data/vendor/libgit2/include/git2/refdb.h +0 -35
  138. data/vendor/libgit2/include/git2/refs.h +93 -31
  139. data/vendor/libgit2/include/git2/refspec.h +17 -0
  140. data/vendor/libgit2/include/git2/remote.h +60 -20
  141. data/vendor/libgit2/include/git2/repository.h +48 -70
  142. data/vendor/libgit2/include/git2/reset.h +3 -3
  143. data/vendor/libgit2/include/git2/revparse.h +22 -0
  144. data/vendor/libgit2/include/git2/stash.h +1 -1
  145. data/vendor/libgit2/include/git2/status.h +131 -56
  146. data/vendor/libgit2/include/git2/strarray.h +2 -2
  147. data/vendor/libgit2/include/git2/submodule.h +16 -16
  148. data/vendor/libgit2/include/git2/sys/commit.h +46 -0
  149. data/vendor/libgit2/include/git2/sys/config.h +71 -0
  150. data/vendor/libgit2/include/git2/sys/index.h +179 -0
  151. data/vendor/libgit2/include/git2/sys/odb_backend.h +86 -0
  152. data/vendor/libgit2/include/git2/sys/refdb_backend.h +158 -0
  153. data/vendor/libgit2/include/git2/sys/refs.h +38 -0
  154. data/vendor/libgit2/include/git2/sys/repository.h +106 -0
  155. data/vendor/libgit2/include/git2/tag.h +44 -18
  156. data/vendor/libgit2/include/git2/trace.h +1 -2
  157. data/vendor/libgit2/include/git2/transport.h +74 -0
  158. data/vendor/libgit2/include/git2/tree.h +12 -22
  159. data/vendor/libgit2/include/git2/types.h +33 -0
  160. data/vendor/libgit2/include/git2/version.h +2 -2
  161. data/vendor/libgit2/src/array.h +66 -0
  162. data/vendor/libgit2/src/attr.c +26 -13
  163. data/vendor/libgit2/src/attr_file.c +3 -2
  164. data/vendor/libgit2/src/attr_file.h +3 -3
  165. data/vendor/libgit2/src/attrcache.h +4 -4
  166. data/vendor/libgit2/src/blob.c +13 -9
  167. data/vendor/libgit2/src/blob.h +2 -2
  168. data/vendor/libgit2/src/branch.c +67 -49
  169. data/vendor/libgit2/src/cache.c +224 -54
  170. data/vendor/libgit2/src/cache.h +33 -20
  171. data/vendor/libgit2/src/checkout.c +145 -85
  172. data/vendor/libgit2/src/clone.c +62 -50
  173. data/vendor/libgit2/src/commit.c +74 -40
  174. data/vendor/libgit2/src/commit.h +2 -3
  175. data/vendor/libgit2/src/commit_list.c +14 -8
  176. data/vendor/libgit2/src/config.c +119 -36
  177. data/vendor/libgit2/src/config.h +3 -0
  178. data/vendor/libgit2/src/config_cache.c +24 -7
  179. data/vendor/libgit2/src/config_file.c +9 -6
  180. data/vendor/libgit2/src/crlf.c +4 -2
  181. data/vendor/libgit2/src/date.c +3 -3
  182. data/vendor/libgit2/src/delta.c +1 -1
  183. data/vendor/libgit2/src/diff.c +681 -303
  184. data/vendor/libgit2/src/diff.h +34 -2
  185. data/vendor/libgit2/src/diff_driver.c +405 -0
  186. data/vendor/libgit2/src/diff_driver.h +49 -0
  187. data/vendor/libgit2/src/diff_file.c +447 -0
  188. data/vendor/libgit2/src/diff_file.h +58 -0
  189. data/vendor/libgit2/src/diff_patch.c +995 -0
  190. data/vendor/libgit2/src/diff_patch.h +46 -0
  191. data/vendor/libgit2/src/diff_print.c +430 -0
  192. data/vendor/libgit2/src/diff_tform.c +464 -203
  193. data/vendor/libgit2/src/diff_xdiff.c +166 -0
  194. data/vendor/libgit2/src/diff_xdiff.h +28 -0
  195. data/vendor/libgit2/src/fetch.c +11 -4
  196. data/vendor/libgit2/src/fileops.c +85 -61
  197. data/vendor/libgit2/src/fileops.h +4 -0
  198. data/vendor/libgit2/src/global.c +10 -2
  199. data/vendor/libgit2/src/global.h +0 -8
  200. data/vendor/libgit2/src/hash/hash_generic.h +3 -3
  201. data/vendor/libgit2/src/hash/hash_win32.h +4 -4
  202. data/vendor/libgit2/src/hashsig.c +0 -1
  203. data/vendor/libgit2/src/ignore.c +68 -28
  204. data/vendor/libgit2/src/ignore.h +10 -1
  205. data/vendor/libgit2/src/index.c +666 -84
  206. data/vendor/libgit2/src/index.h +6 -0
  207. data/vendor/libgit2/src/indexer.c +10 -28
  208. data/vendor/libgit2/src/iterator.c +427 -283
  209. data/vendor/libgit2/src/iterator.h +58 -4
  210. data/vendor/libgit2/src/merge.c +1892 -32
  211. data/vendor/libgit2/src/merge.h +132 -5
  212. data/vendor/libgit2/src/merge_file.c +174 -0
  213. data/vendor/libgit2/src/merge_file.h +71 -0
  214. data/vendor/libgit2/src/mwindow.c +1 -1
  215. data/vendor/libgit2/src/notes.c +45 -48
  216. data/vendor/libgit2/src/object.c +89 -127
  217. data/vendor/libgit2/src/object.h +0 -1
  218. data/vendor/libgit2/src/object_api.c +129 -0
  219. data/vendor/libgit2/src/odb.c +156 -59
  220. data/vendor/libgit2/src/odb.h +5 -2
  221. data/vendor/libgit2/src/odb_loose.c +31 -17
  222. data/vendor/libgit2/src/odb_pack.c +39 -43
  223. data/vendor/libgit2/src/oid.c +62 -27
  224. data/vendor/libgit2/src/oid.h +33 -0
  225. data/vendor/libgit2/src/oidmap.h +4 -6
  226. data/vendor/libgit2/src/pack-objects.c +54 -22
  227. data/vendor/libgit2/src/pack.c +98 -56
  228. data/vendor/libgit2/src/pack.h +3 -1
  229. data/vendor/libgit2/src/pathspec.c +26 -1
  230. data/vendor/libgit2/src/pathspec.h +14 -0
  231. data/vendor/libgit2/src/pool.c +5 -0
  232. data/vendor/libgit2/src/posix.c +2 -2
  233. data/vendor/libgit2/src/posix.h +3 -0
  234. data/vendor/libgit2/src/push.c +13 -10
  235. data/vendor/libgit2/src/refdb.c +82 -62
  236. data/vendor/libgit2/src/refdb.h +16 -16
  237. data/vendor/libgit2/src/refdb_fs.c +386 -133
  238. data/vendor/libgit2/src/reflog.c +3 -1
  239. data/vendor/libgit2/src/refs.c +247 -221
  240. data/vendor/libgit2/src/refs.h +2 -1
  241. data/vendor/libgit2/src/refspec.c +18 -1
  242. data/vendor/libgit2/src/refspec.h +3 -1
  243. data/vendor/libgit2/src/remote.c +434 -253
  244. data/vendor/libgit2/src/remote.h +5 -3
  245. data/vendor/libgit2/src/repository.c +197 -111
  246. data/vendor/libgit2/src/repository.h +26 -5
  247. data/vendor/libgit2/src/reset.c +1 -1
  248. data/vendor/libgit2/src/revparse.c +84 -79
  249. data/vendor/libgit2/src/revwalk.c +1 -1
  250. data/vendor/libgit2/src/signature.c +22 -10
  251. data/vendor/libgit2/src/stash.c +5 -2
  252. data/vendor/libgit2/src/status.c +311 -107
  253. data/vendor/libgit2/src/status.h +23 -0
  254. data/vendor/libgit2/src/submodule.c +21 -13
  255. data/vendor/libgit2/src/tag.c +42 -31
  256. data/vendor/libgit2/src/tag.h +2 -3
  257. data/vendor/libgit2/src/thread-utils.h +105 -3
  258. data/vendor/libgit2/src/trace.c +1 -2
  259. data/vendor/libgit2/src/trace.h +3 -3
  260. data/vendor/libgit2/src/transport.c +18 -6
  261. data/vendor/libgit2/src/transports/cred.c +103 -1
  262. data/vendor/libgit2/src/transports/local.c +19 -9
  263. data/vendor/libgit2/src/transports/smart_protocol.c +32 -12
  264. data/vendor/libgit2/src/transports/ssh.c +519 -0
  265. data/vendor/libgit2/src/transports/winhttp.c +3 -1
  266. data/vendor/libgit2/src/tree.c +26 -28
  267. data/vendor/libgit2/src/tree.h +3 -3
  268. data/vendor/libgit2/src/unix/posix.h +2 -0
  269. data/vendor/libgit2/src/util.c +43 -6
  270. data/vendor/libgit2/src/util.h +40 -12
  271. data/vendor/libgit2/src/vector.c +3 -5
  272. data/vendor/libgit2/src/vector.h +9 -0
  273. data/vendor/libgit2/src/win32/dir.c +1 -1
  274. data/vendor/libgit2/src/win32/error.c +2 -0
  275. data/vendor/libgit2/src/win32/findfile.c +3 -6
  276. data/vendor/libgit2/src/win32/posix_w32.c +85 -59
  277. data/vendor/libgit2/src/win32/pthread.c +16 -8
  278. data/vendor/libgit2/src/win32/pthread.h +7 -4
  279. metadata +407 -306
  280. data/test/coverage/HEAD.json +0 -1
  281. data/vendor/libgit2/include/git2/refdb_backend.h +0 -109
  282. data/vendor/libgit2/src/diff_output.c +0 -1819
  283. data/vendor/libgit2/src/diff_output.h +0 -93
@@ -483,8 +483,10 @@ int git_reflog_drop(
483
483
 
484
484
  entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx);
485
485
 
486
- if (entry == NULL)
486
+ if (entry == NULL) {
487
+ giterr_set(GITERR_REFERENCE, "No reflog entry at index "PRIuZ, idx);
487
488
  return GIT_ENOTFOUND;
489
+ }
488
490
 
489
491
  reflog_entry_free(entry);
490
492
 
@@ -9,6 +9,7 @@
9
9
  #include "hash.h"
10
10
  #include "repository.h"
11
11
  #include "fileops.h"
12
+ #include "filebuf.h"
12
13
  #include "pack.h"
13
14
  #include "reflog.h"
14
15
  #include "refdb.h"
@@ -19,7 +20,7 @@
19
20
  #include <git2/branch.h>
20
21
  #include <git2/refs.h>
21
22
  #include <git2/refdb.h>
22
- #include <git2/refdb_backend.h>
23
+ #include <git2/sys/refs.h>
23
24
 
24
25
  GIT__USE_STRMAP;
25
26
 
@@ -31,7 +32,7 @@ enum {
31
32
  GIT_PACKREF_WAS_LOOSE = 2
32
33
  };
33
34
 
34
- static git_reference *alloc_ref(git_refdb *refdb, const char *name)
35
+ static git_reference *alloc_ref(const char *name)
35
36
  {
36
37
  git_reference *ref;
37
38
  size_t namelen = strlen(name);
@@ -39,22 +40,19 @@ static git_reference *alloc_ref(git_refdb *refdb, const char *name)
39
40
  if ((ref = git__calloc(1, sizeof(git_reference) + namelen + 1)) == NULL)
40
41
  return NULL;
41
42
 
42
- ref->db = refdb;
43
43
  memcpy(ref->name, name, namelen + 1);
44
44
 
45
45
  return ref;
46
46
  }
47
47
 
48
48
  git_reference *git_reference__alloc_symbolic(
49
- git_refdb *refdb,
50
- const char *name,
51
- const char *target)
49
+ const char *name, const char *target)
52
50
  {
53
51
  git_reference *ref;
54
52
 
55
- assert(refdb && name && target);
53
+ assert(name && target);
56
54
 
57
- ref = alloc_ref(refdb, name);
55
+ ref = alloc_ref(name);
58
56
  if (!ref)
59
57
  return NULL;
60
58
 
@@ -69,16 +67,15 @@ git_reference *git_reference__alloc_symbolic(
69
67
  }
70
68
 
71
69
  git_reference *git_reference__alloc(
72
- git_refdb *refdb,
73
70
  const char *name,
74
71
  const git_oid *oid,
75
72
  const git_oid *peel)
76
73
  {
77
74
  git_reference *ref;
78
75
 
79
- assert(refdb && name && oid);
76
+ assert(name && oid);
80
77
 
81
- ref = alloc_ref(refdb, name);
78
+ ref = alloc_ref(name);
82
79
  if (!ref)
83
80
  return NULL;
84
81
 
@@ -99,123 +96,15 @@ void git_reference_free(git_reference *reference)
99
96
  if (reference->type == GIT_REF_SYMBOLIC)
100
97
  git__free(reference->target.symbolic);
101
98
 
102
- git__free(reference);
103
- }
104
-
105
- struct reference_available_t {
106
- const char *new_ref;
107
- const char *old_ref;
108
- int available;
109
- };
110
-
111
- static int _reference_available_cb(const char *ref, void *data)
112
- {
113
- struct reference_available_t *d;
114
-
115
- assert(ref && data);
116
- d = (struct reference_available_t *)data;
117
-
118
- if (!d->old_ref || strcmp(d->old_ref, ref)) {
119
- size_t reflen = strlen(ref);
120
- size_t newlen = strlen(d->new_ref);
121
- size_t cmplen = reflen < newlen ? reflen : newlen;
122
- const char *lead = reflen < newlen ? d->new_ref : ref;
123
-
124
- if (!strncmp(d->new_ref, ref, cmplen) && lead[cmplen] == '/') {
125
- d->available = 0;
126
- return -1;
127
- }
128
- }
129
-
130
- return 0;
131
- }
99
+ if (reference->db)
100
+ GIT_REFCOUNT_DEC(reference->db, git_refdb__free);
132
101
 
133
- static int reference_path_available(
134
- git_repository *repo,
135
- const char *ref,
136
- const char* old_ref)
137
- {
138
- int error;
139
- struct reference_available_t data;
140
-
141
- data.new_ref = ref;
142
- data.old_ref = old_ref;
143
- data.available = 1;
144
-
145
- error = git_reference_foreach(
146
- repo, GIT_REF_LISTALL, _reference_available_cb, (void *)&data);
147
- if (error < 0)
148
- return error;
149
-
150
- if (!data.available) {
151
- giterr_set(GITERR_REFERENCE,
152
- "The path to reference '%s' collides with an existing one", ref);
153
- return -1;
154
- }
155
-
156
- return 0;
157
- }
158
-
159
- /*
160
- * Check if a reference could be written to disk, based on:
161
- *
162
- * - Whether a reference with the same name already exists,
163
- * and we are allowing or disallowing overwrites
164
- *
165
- * - Whether the name of the reference would collide with
166
- * an existing path
167
- */
168
- static int reference_can_write(
169
- git_repository *repo,
170
- const char *refname,
171
- const char *previous_name,
172
- int force)
173
- {
174
- git_refdb *refdb;
175
-
176
- if (git_repository_refdb__weakptr(&refdb, repo) < 0)
177
- return -1;
178
-
179
- /* see if the reference shares a path with an existing reference;
180
- * if a path is shared, we cannot create the reference, even when forcing */
181
- if (reference_path_available(repo, refname, previous_name) < 0)
182
- return -1;
183
-
184
- /* check if the reference actually exists, but only if we are not forcing
185
- * the rename. If we are forcing, it's OK to overwrite */
186
- if (!force) {
187
- int exists;
188
-
189
- if (git_refdb_exists(&exists, refdb, refname) < 0)
190
- return -1;
191
-
192
- /* We cannot proceed if the reference already exists and we're not forcing
193
- * the rename; the existing one would be overwritten */
194
- if (exists) {
195
- giterr_set(GITERR_REFERENCE,
196
- "A reference with that name (%s) already exists", refname);
197
- return GIT_EEXISTS;
198
- }
199
- }
200
-
201
- /* FIXME: if the reference exists and we are forcing, do we really need to
202
- * remove the reference first?
203
- *
204
- * Two cases:
205
- *
206
- * - the reference already exists and is loose: not a problem, the file
207
- * gets overwritten on disk
208
- *
209
- * - the reference already exists and is packed: we write a new one as
210
- * loose, which by all means renders the packed one useless
211
- */
212
-
213
- return 0;
102
+ git__free(reference);
214
103
  }
215
104
 
216
105
  int git_reference_delete(git_reference *ref)
217
106
  {
218
- return git_refdb_delete(ref->db, ref);
107
+ return git_refdb_delete(ref->db, ref->name);
219
108
  }
220
109
 
221
110
  int git_reference_lookup(git_reference **ref_out,
@@ -258,10 +147,10 @@ int git_reference_lookup_resolved(
258
147
  max_nesting = MAX_NESTING_LEVEL;
259
148
  else if (max_nesting < 0)
260
149
  max_nesting = DEFAULT_NESTING_LEVEL;
261
-
150
+
262
151
  strncpy(scan_name, name, GIT_REFNAME_MAX);
263
152
  scan_type = GIT_REF_SYMBOLIC;
264
-
153
+
265
154
  if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
266
155
  return -1;
267
156
 
@@ -279,7 +168,7 @@ int git_reference_lookup_resolved(
279
168
 
280
169
  if ((error = git_refdb_lookup(&ref, refdb, scan_name)) < 0)
281
170
  return error;
282
-
171
+
283
172
  scan_type = ref->type;
284
173
  }
285
174
 
@@ -294,6 +183,67 @@ int git_reference_lookup_resolved(
294
183
  return 0;
295
184
  }
296
185
 
186
+ int git_reference_dwim(git_reference **out, git_repository *repo, const char *refname)
187
+ {
188
+ int error = 0, i;
189
+ bool fallbackmode = true, foundvalid = false;
190
+ git_reference *ref;
191
+ git_buf refnamebuf = GIT_BUF_INIT, name = GIT_BUF_INIT;
192
+
193
+ static const char* formatters[] = {
194
+ "%s",
195
+ GIT_REFS_DIR "%s",
196
+ GIT_REFS_TAGS_DIR "%s",
197
+ GIT_REFS_HEADS_DIR "%s",
198
+ GIT_REFS_REMOTES_DIR "%s",
199
+ GIT_REFS_REMOTES_DIR "%s/" GIT_HEAD_FILE,
200
+ NULL
201
+ };
202
+
203
+ if (*refname)
204
+ git_buf_puts(&name, refname);
205
+ else {
206
+ git_buf_puts(&name, GIT_HEAD_FILE);
207
+ fallbackmode = false;
208
+ }
209
+
210
+ for (i = 0; formatters[i] && (fallbackmode || i == 0); i++) {
211
+
212
+ git_buf_clear(&refnamebuf);
213
+
214
+ if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0)
215
+ goto cleanup;
216
+
217
+ if (!git_reference_is_valid_name(git_buf_cstr(&refnamebuf))) {
218
+ error = GIT_EINVALIDSPEC;
219
+ continue;
220
+ }
221
+ foundvalid = true;
222
+
223
+ error = git_reference_lookup_resolved(&ref, repo, git_buf_cstr(&refnamebuf), -1);
224
+
225
+ if (!error) {
226
+ *out = ref;
227
+ error = 0;
228
+ goto cleanup;
229
+ }
230
+
231
+ if (error != GIT_ENOTFOUND)
232
+ goto cleanup;
233
+ }
234
+
235
+ cleanup:
236
+ if (error && !foundvalid) {
237
+ /* never found a valid reference name */
238
+ giterr_set(GITERR_REFERENCE,
239
+ "Could not use '%s' as valid reference name", git_buf_cstr(&name));
240
+ }
241
+
242
+ git_buf_free(&name);
243
+ git_buf_free(&refnamebuf);
244
+ return error;
245
+ }
246
+
297
247
  /**
298
248
  * Getters
299
249
  */
@@ -357,29 +307,32 @@ static int reference__create(
357
307
  git_refdb *refdb;
358
308
  git_reference *ref = NULL;
359
309
  int error = 0;
360
-
310
+
361
311
  if (ref_out)
362
312
  *ref_out = NULL;
363
313
 
364
- if ((error = git_reference__normalize_name_lax(normalized, sizeof(normalized), name)) < 0 ||
365
- (error = reference_can_write(repo, normalized, NULL, force)) < 0 ||
366
- (error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
314
+ error = git_reference__normalize_name_lax(normalized, sizeof(normalized), name);
315
+ if (error < 0)
316
+ return error;
317
+
318
+ error = git_repository_refdb__weakptr(&refdb, repo);
319
+ if (error < 0)
367
320
  return error;
368
321
 
369
322
  if (oid != NULL) {
370
323
  assert(symbolic == NULL);
371
- ref = git_reference__alloc(refdb, name, oid, NULL);
324
+ ref = git_reference__alloc(normalized, oid, NULL);
372
325
  } else {
373
- ref = git_reference__alloc_symbolic(refdb, name, symbolic);
326
+ ref = git_reference__alloc_symbolic(normalized, symbolic);
374
327
  }
375
-
328
+
376
329
  GITERR_CHECK_ALLOC(ref);
377
330
 
378
- if ((error = git_refdb_write(refdb, ref)) < 0) {
331
+ if ((error = git_refdb_write(refdb, ref, force)) < 0) {
379
332
  git_reference_free(ref);
380
333
  return error;
381
334
  }
382
-
335
+
383
336
  if (ref_out == NULL)
384
337
  git_reference_free(ref);
385
338
  else
@@ -399,17 +352,17 @@ int git_reference_create(
399
352
  int error = 0;
400
353
 
401
354
  assert(repo && name && oid);
402
-
355
+
403
356
  /* Sanity check the reference being created - target must exist. */
404
357
  if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
405
358
  return error;
406
-
359
+
407
360
  if (!git_odb_exists(odb, oid)) {
408
361
  giterr_set(GITERR_REFERENCE,
409
362
  "Target OID for the reference doesn't exist on the repository");
410
363
  return -1;
411
364
  }
412
-
365
+
413
366
  return reference__create(ref_out, repo, name, oid, NULL, force);
414
367
  }
415
368
 
@@ -424,7 +377,7 @@ int git_reference_symbolic_create(
424
377
  int error = 0;
425
378
 
426
379
  assert(repo && name && target);
427
-
380
+
428
381
  if ((error = git_reference__normalize_name_lax(
429
382
  normalized, sizeof(normalized), target)) < 0)
430
383
  return error;
@@ -438,7 +391,7 @@ int git_reference_set_target(
438
391
  const git_oid *id)
439
392
  {
440
393
  assert(out && ref && id);
441
-
394
+
442
395
  if (ref->type != GIT_REF_OID) {
443
396
  giterr_set(GITERR_REFERENCE, "Cannot set OID on symbolic reference");
444
397
  return -1;
@@ -453,13 +406,13 @@ int git_reference_symbolic_set_target(
453
406
  const char *target)
454
407
  {
455
408
  assert(out && ref && target);
456
-
409
+
457
410
  if (ref->type != GIT_REF_SYMBOLIC) {
458
411
  giterr_set(GITERR_REFERENCE,
459
412
  "Cannot set symbolic target on a direct reference");
460
413
  return -1;
461
414
  }
462
-
415
+
463
416
  return git_reference_symbolic_create(out, ref->db->repo, ref->name, target, 1);
464
417
  }
465
418
 
@@ -472,75 +425,41 @@ int git_reference_rename(
472
425
  unsigned int normalization_flags;
473
426
  char normalized[GIT_REFNAME_MAX];
474
427
  bool should_head_be_updated = false;
475
- git_reference *result = NULL;
476
428
  int error = 0;
477
429
  int reference_has_log;
478
-
479
- *out = NULL;
480
430
 
481
431
  normalization_flags = ref->type == GIT_REF_SYMBOLIC ?
482
432
  GIT_REF_FORMAT_ALLOW_ONELEVEL : GIT_REF_FORMAT_NORMAL;
483
433
 
484
434
  if ((error = git_reference_normalize_name(
485
- normalized, sizeof(normalized), new_name, normalization_flags)) < 0 ||
486
- (error = reference_can_write(ref->db->repo, normalized, ref->name, force)) < 0)
435
+ normalized, sizeof(normalized), new_name, normalization_flags)) < 0)
487
436
  return error;
488
437
 
489
- /*
490
- * Create the new reference.
491
- */
492
- if (ref->type == GIT_REF_OID) {
493
- result = git_reference__alloc(ref->db, new_name,
494
- &ref->target.oid, &ref->peel);
495
- } else if (ref->type == GIT_REF_SYMBOLIC) {
496
- result = git_reference__alloc_symbolic(ref->db, new_name, ref->target.symbolic);
497
- } else {
498
- assert(0);
499
- }
500
-
501
- if (result == NULL)
502
- return -1;
503
-
504
438
  /* Check if we have to update HEAD. */
505
439
  if ((error = git_branch_is_head(ref)) < 0)
506
- goto on_error;
440
+ return error;
507
441
 
508
442
  should_head_be_updated = (error > 0);
509
443
 
510
- /* Now delete the old ref and save the new one. */
511
- if ((error = git_refdb_delete(ref->db, ref)) < 0)
512
- goto on_error;
513
-
514
- /* Save the new reference. */
515
- if ((error = git_refdb_write(ref->db, result)) < 0)
516
- goto rollback;
517
-
444
+ if ((error = git_refdb_rename(out, ref->db, ref->name, new_name, force)) < 0)
445
+ return error;
446
+
518
447
  /* Update HEAD it was poiting to the reference being renamed. */
519
- if (should_head_be_updated && (error = git_repository_set_head(ref->db->repo, new_name)) < 0) {
448
+ if (should_head_be_updated &&
449
+ (error = git_repository_set_head(ref->db->repo, new_name)) < 0) {
520
450
  giterr_set(GITERR_REFERENCE, "Failed to update HEAD after renaming reference");
521
- goto on_error;
451
+ return error;
522
452
  }
523
453
 
524
454
  /* Rename the reflog file, if it exists. */
525
455
  reference_has_log = git_reference_has_log(ref);
526
- if (reference_has_log < 0) {
527
- error = reference_has_log;
528
- goto on_error;
529
- }
530
- if (reference_has_log && (error = git_reflog_rename(ref, new_name)) < 0)
531
- goto on_error;
532
-
533
- *out = result;
534
-
535
- return error;
536
-
537
- rollback:
538
- git_refdb_write(ref->db, ref);
456
+ if (reference_has_log < 0)
457
+ return reference_has_log;
539
458
 
540
- on_error:
541
- git_reference_free(result);
459
+ if (reference_has_log && (error = git_reflog_rename(ref, new_name)) < 0)
460
+ return error;
542
461
 
543
- return error;
462
+ return 0;
544
463
  }
545
464
 
546
465
  int git_reference_resolve(git_reference **ref_out, const git_reference *ref)
@@ -548,7 +467,7 @@ int git_reference_resolve(git_reference **ref_out, const git_reference *ref)
548
467
  switch (git_reference_type(ref)) {
549
468
  case GIT_REF_OID:
550
469
  return git_reference_lookup(ref_out, ref->db->repo, ref->name);
551
-
470
+
552
471
  case GIT_REF_SYMBOLIC:
553
472
  return git_reference_lookup_resolved(ref_out, ref->db->repo, ref->target.symbolic, -1);
554
473
 
@@ -560,14 +479,120 @@ int git_reference_resolve(git_reference **ref_out, const git_reference *ref)
560
479
 
561
480
  int git_reference_foreach(
562
481
  git_repository *repo,
563
- unsigned int list_flags,
564
482
  git_reference_foreach_cb callback,
565
483
  void *payload)
484
+ {
485
+ git_reference_iterator *iter;
486
+ git_reference *ref;
487
+ int error;
488
+
489
+ if (git_reference_iterator_new(&iter, repo) < 0)
490
+ return -1;
491
+
492
+ while ((error = git_reference_next(&ref, iter)) == 0) {
493
+ if (callback(ref, payload)) {
494
+ error = GIT_EUSER;
495
+ goto out;
496
+ }
497
+ }
498
+
499
+ if (error == GIT_ITEROVER)
500
+ error = 0;
501
+
502
+ out:
503
+ git_reference_iterator_free(iter);
504
+ return error;
505
+ }
506
+
507
+ int git_reference_foreach_name(
508
+ git_repository *repo,
509
+ git_reference_foreach_name_cb callback,
510
+ void *payload)
511
+ {
512
+ git_reference_iterator *iter;
513
+ const char *refname;
514
+ int error;
515
+
516
+ if (git_reference_iterator_new(&iter, repo) < 0)
517
+ return -1;
518
+
519
+ while ((error = git_reference_next_name(&refname, iter)) == 0) {
520
+ if (callback(refname, payload)) {
521
+ error = GIT_EUSER;
522
+ goto out;
523
+ }
524
+ }
525
+
526
+ if (error == GIT_ITEROVER)
527
+ error = 0;
528
+
529
+ out:
530
+ git_reference_iterator_free(iter);
531
+ return error;
532
+ }
533
+
534
+ int git_reference_foreach_glob(
535
+ git_repository *repo,
536
+ const char *glob,
537
+ git_reference_foreach_name_cb callback,
538
+ void *payload)
539
+ {
540
+ git_reference_iterator *iter;
541
+ const char *refname;
542
+ int error;
543
+
544
+ if (git_reference_iterator_glob_new(&iter, repo, glob) < 0)
545
+ return -1;
546
+
547
+ while ((error = git_reference_next_name(&refname, iter)) == 0) {
548
+ if (callback(refname, payload)) {
549
+ error = GIT_EUSER;
550
+ goto out;
551
+ }
552
+ }
553
+
554
+ if (error == GIT_ITEROVER)
555
+ error = 0;
556
+
557
+ out:
558
+ git_reference_iterator_free(iter);
559
+ return error;
560
+ }
561
+
562
+ int git_reference_iterator_new(git_reference_iterator **out, git_repository *repo)
566
563
  {
567
564
  git_refdb *refdb;
568
- git_repository_refdb__weakptr(&refdb, repo);
569
565
 
570
- return git_refdb_foreach(refdb, list_flags, callback, payload);
566
+ if (git_repository_refdb__weakptr(&refdb, repo) < 0)
567
+ return -1;
568
+
569
+ return git_refdb_iterator(out, refdb, NULL);
570
+ }
571
+
572
+ int git_reference_iterator_glob_new(
573
+ git_reference_iterator **out, git_repository *repo, const char *glob)
574
+ {
575
+ git_refdb *refdb;
576
+
577
+ if (git_repository_refdb__weakptr(&refdb, repo) < 0)
578
+ return -1;
579
+
580
+ return git_refdb_iterator(out, refdb, glob);
581
+ }
582
+
583
+ int git_reference_next(git_reference **out, git_reference_iterator *iter)
584
+ {
585
+ return git_refdb_iterator_next(out, iter);
586
+ }
587
+
588
+ int git_reference_next_name(const char **out, git_reference_iterator *iter)
589
+ {
590
+ return git_refdb_iterator_next_name(out, iter);
591
+ }
592
+
593
+ void git_reference_iterator_free(git_reference_iterator *iter)
594
+ {
595
+ git_refdb_iterator_free(iter);
571
596
  }
572
597
 
573
598
  static int cb__reflist_add(const char *ref, void *data)
@@ -577,8 +602,7 @@ static int cb__reflist_add(const char *ref, void *data)
577
602
 
578
603
  int git_reference_list(
579
604
  git_strarray *array,
580
- git_repository *repo,
581
- unsigned int list_flags)
605
+ git_repository *repo)
582
606
  {
583
607
  git_vector ref_list;
584
608
 
@@ -590,8 +614,8 @@ int git_reference_list(
590
614
  if (git_vector_init(&ref_list, 8, NULL) < 0)
591
615
  return -1;
592
616
 
593
- if (git_reference_foreach(
594
- repo, list_flags, &cb__reflist_add, (void *)&ref_list) < 0) {
617
+ if (git_reference_foreach_name(
618
+ repo, &cb__reflist_add, (void *)&ref_list) < 0) {
595
619
  git_vector_free(&ref_list);
596
620
  return -1;
597
621
  }
@@ -754,6 +778,7 @@ int git_reference__normalize_name(
754
778
  goto cleanup;
755
779
 
756
780
  if ((segments_count == 1 ) &&
781
+ !(flags & GIT_REF_FORMAT_REFSPEC_SHORTHAND) &&
757
782
  !(is_all_caps_and_underscore(name, (size_t)segment_len) ||
758
783
  ((flags & GIT_REF_FORMAT_REFSPEC_PATTERN) && !strcmp("*", name))))
759
784
  goto cleanup;
@@ -833,7 +858,7 @@ int git_reference_cmp(git_reference *ref1, git_reference *ref2)
833
858
  if (type1 == GIT_REF_SYMBOLIC)
834
859
  return strcmp(ref1->target.symbolic, ref2->target.symbolic);
835
860
 
836
- return git_oid_cmp(&ref1->target.oid, &ref2->target.oid);
861
+ return git_oid__cmp(&ref1->target.oid, &ref2->target.oid);
837
862
  }
838
863
 
839
864
  static int reference__update_terminal(
@@ -845,9 +870,11 @@ static int reference__update_terminal(
845
870
  git_reference *ref;
846
871
  int error = 0;
847
872
 
848
- if (nesting > MAX_NESTING_LEVEL)
873
+ if (nesting > MAX_NESTING_LEVEL) {
874
+ giterr_set(GITERR_REFERENCE, "Reference chain too deep (%d)", nesting);
849
875
  return GIT_ENOTFOUND;
850
-
876
+ }
877
+
851
878
  error = git_reference_lookup(&ref, repo, ref_name);
852
879
 
853
880
  /* If we haven't found the reference at all, create a new reference. */
@@ -855,10 +882,10 @@ static int reference__update_terminal(
855
882
  giterr_clear();
856
883
  return git_reference_create(NULL, repo, ref_name, oid, 0);
857
884
  }
858
-
885
+
859
886
  if (error < 0)
860
887
  return error;
861
-
888
+
862
889
  /* If the ref is a symbolic reference, follow its target. */
863
890
  if (git_reference_type(ref) == GIT_REF_SYMBOLIC) {
864
891
  error = reference__update_terminal(repo, git_reference_symbolic_target(ref), oid,
@@ -868,7 +895,7 @@ static int reference__update_terminal(
868
895
  git_reference_free(ref);
869
896
  error = git_reference_create(NULL, repo, ref_name, oid, 1);
870
897
  }
871
-
898
+
872
899
  return error;
873
900
  }
874
901
 
@@ -885,24 +912,6 @@ int git_reference__update_terminal(
885
912
  return reference__update_terminal(repo, ref_name, oid, 0);
886
913
  }
887
914
 
888
- int git_reference_foreach_glob(
889
- git_repository *repo,
890
- const char *glob,
891
- unsigned int list_flags,
892
- int (*callback)(
893
- const char *reference_name,
894
- void *payload),
895
- void *payload)
896
- {
897
- git_refdb *refdb;
898
-
899
- assert(repo && glob && callback);
900
-
901
- git_repository_refdb__weakptr(&refdb, repo);
902
-
903
- return git_refdb_foreach_glob(refdb, glob, list_flags, callback, payload);
904
- }
905
-
906
915
  int git_reference_has_log(
907
916
  git_reference *ref)
908
917
  {
@@ -1015,3 +1024,20 @@ int git_reference_is_valid_name(
1015
1024
  refname,
1016
1025
  GIT_REF_FORMAT_ALLOW_ONELEVEL);
1017
1026
  }
1027
+
1028
+ const char *git_reference_shorthand(git_reference *ref)
1029
+ {
1030
+ const char *name = ref->name;
1031
+
1032
+ if (!git__prefixcmp(name, GIT_REFS_HEADS_DIR))
1033
+ return name + strlen(GIT_REFS_HEADS_DIR);
1034
+ else if (!git__prefixcmp(name, GIT_REFS_TAGS_DIR))
1035
+ return name + strlen(GIT_REFS_TAGS_DIR);
1036
+ else if (!git__prefixcmp(name, GIT_REFS_REMOTES_DIR))
1037
+ return name + strlen(GIT_REFS_REMOTES_DIR);
1038
+ else if (!git__prefixcmp(name, GIT_REFS_DIR))
1039
+ return name + strlen(GIT_REFS_DIR);
1040
+
1041
+ /* No shorthands are avaiable, so just return the name */
1042
+ return name;
1043
+ }