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
@@ -242,3 +242,22 @@ int git_refdb_init_backend(git_refdb_backend *backend, unsigned int version)
242
242
  backend, version, git_refdb_backend, GIT_REFDB_BACKEND_INIT);
243
243
  return 0;
244
244
  }
245
+
246
+ int git_refdb_lock(void **payload, git_refdb *db, const char *refname)
247
+ {
248
+ assert(payload && db && refname);
249
+
250
+ if (!db->backend->lock) {
251
+ giterr_set(GITERR_REFERENCE, "backend does not support locking");
252
+ return -1;
253
+ }
254
+
255
+ return db->backend->lock(payload, db->backend, refname);
256
+ }
257
+
258
+ int git_refdb_unlock(git_refdb *db, void *payload, int success, int update_reflog, const git_reference *ref, const git_signature *sig, const char *message)
259
+ {
260
+ assert(db);
261
+
262
+ return db->backend->unlock(db->backend, payload, success, update_reflog, ref, sig, message);
263
+ }
@@ -51,6 +51,7 @@ int git_refdb_reflog_write(git_reflog *reflog);
51
51
  int git_refdb_has_log(git_refdb *db, const char *refname);
52
52
  int git_refdb_ensure_log(git_refdb *refdb, const char *refname);
53
53
 
54
-
54
+ int git_refdb_lock(void **payload, git_refdb *db, const char *refname);
55
+ int git_refdb_unlock(git_refdb *db, void *payload, int success, int update_reflog, const git_reference *ref, const git_signature *sig, const char *message);
55
56
 
56
57
  #endif
@@ -707,16 +707,11 @@ static int reference_path_available(
707
707
 
708
708
  static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *name)
709
709
  {
710
- int error;
710
+ int error;
711
711
  git_buf ref_path = GIT_BUF_INIT;
712
712
 
713
713
  assert(file && backend && name);
714
714
 
715
- if (!git_path_isvalid(backend->repo, name, GIT_PATH_REJECT_DEFAULTS)) {
716
- giterr_set(GITERR_INVALID, "Invalid reference name '%s'.", name);
717
- return GIT_EINVALIDSPEC;
718
- }
719
-
720
715
  /* Remove a possibly existing empty directory hierarchy
721
716
  * which name would collide with the reference name
722
717
  */
@@ -750,6 +745,57 @@ static int loose_commit(git_filebuf *file, const git_reference *ref)
750
745
  return git_filebuf_commit(file);
751
746
  }
752
747
 
748
+ static int refdb_fs_backend__lock(void **out, git_refdb_backend *_backend, const char *refname)
749
+ {
750
+ int error;
751
+ git_filebuf *lock;
752
+ refdb_fs_backend *backend = (refdb_fs_backend *) _backend;
753
+
754
+ lock = git__calloc(1, sizeof(git_filebuf));
755
+ GITERR_CHECK_ALLOC(lock);
756
+
757
+ if ((error = loose_lock(lock, backend, refname)) < 0) {
758
+ git__free(lock);
759
+ return error;
760
+ }
761
+
762
+ *out = lock;
763
+ return 0;
764
+ }
765
+
766
+ static int refdb_fs_backend__write_tail(
767
+ git_refdb_backend *_backend,
768
+ const git_reference *ref,
769
+ git_filebuf *file,
770
+ int update_reflog,
771
+ const git_signature *who,
772
+ const char *message,
773
+ const git_oid *old_id,
774
+ const char *old_target);
775
+
776
+ static int refdb_fs_backend__delete_tail(
777
+ git_refdb_backend *_backend,
778
+ git_filebuf *file,
779
+ const char *ref_name,
780
+ const git_oid *old_id, const char *old_target);
781
+
782
+ static int refdb_fs_backend__unlock(git_refdb_backend *backend, void *payload, int success, int update_reflog,
783
+ const git_reference *ref, const git_signature *sig, const char *message)
784
+ {
785
+ git_filebuf *lock = (git_filebuf *) payload;
786
+ int error = 0;
787
+
788
+ if (success == 2)
789
+ error = refdb_fs_backend__delete_tail(backend, lock, ref->name, NULL, NULL);
790
+ else if (success)
791
+ error = refdb_fs_backend__write_tail(backend, ref, lock, update_reflog, sig, message, NULL, NULL);
792
+ else
793
+ git_filebuf_cleanup(lock);
794
+
795
+ git__free(lock);
796
+ return error;
797
+ }
798
+
753
799
  /*
754
800
  * Find out what object this reference resolves to.
755
801
  *
@@ -1068,7 +1114,6 @@ cleanup:
1068
1114
  return error;
1069
1115
  }
1070
1116
 
1071
-
1072
1117
  static int refdb_fs_backend__write(
1073
1118
  git_refdb_backend *_backend,
1074
1119
  const git_reference *ref,
@@ -1080,9 +1125,7 @@ static int refdb_fs_backend__write(
1080
1125
  {
1081
1126
  refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
1082
1127
  git_filebuf file = GIT_FILEBUF_INIT;
1083
- int error = 0, cmp = 0, should_write;
1084
- const char *new_target = NULL;
1085
- const git_oid *new_id = NULL;
1128
+ int error = 0;
1086
1129
 
1087
1130
  assert(backend);
1088
1131
 
@@ -1094,6 +1137,24 @@ static int refdb_fs_backend__write(
1094
1137
  if ((error = loose_lock(&file, backend, ref->name)) < 0)
1095
1138
  return error;
1096
1139
 
1140
+ return refdb_fs_backend__write_tail(_backend, ref, &file, true, who, message, old_id, old_target);
1141
+ }
1142
+
1143
+ static int refdb_fs_backend__write_tail(
1144
+ git_refdb_backend *_backend,
1145
+ const git_reference *ref,
1146
+ git_filebuf *file,
1147
+ int update_reflog,
1148
+ const git_signature *who,
1149
+ const char *message,
1150
+ const git_oid *old_id,
1151
+ const char *old_target)
1152
+ {
1153
+ refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
1154
+ int error = 0, cmp = 0, should_write;
1155
+ const char *new_target = NULL;
1156
+ const git_oid *new_id = NULL;
1157
+
1097
1158
  if ((error = cmp_old_ref(&cmp, _backend, ref->name, old_id, old_target)) < 0)
1098
1159
  goto on_error;
1099
1160
 
@@ -1118,20 +1179,22 @@ static int refdb_fs_backend__write(
1118
1179
  goto on_error; /* not really error */
1119
1180
  }
1120
1181
 
1121
- if ((error = should_write_reflog(&should_write, backend->repo, ref->name)) < 0)
1122
- goto on_error;
1123
-
1124
- if (should_write) {
1125
- if ((error = reflog_append(backend, ref, NULL, NULL, who, message)) < 0)
1126
- goto on_error;
1127
- if ((error = maybe_append_head(backend, ref, who, message)) < 0)
1182
+ if (update_reflog) {
1183
+ if ((error = should_write_reflog(&should_write, backend->repo, ref->name)) < 0)
1128
1184
  goto on_error;
1185
+
1186
+ if (should_write) {
1187
+ if ((error = reflog_append(backend, ref, NULL, NULL, who, message)) < 0)
1188
+ goto on_error;
1189
+ if ((error = maybe_append_head(backend, ref, who, message)) < 0)
1190
+ goto on_error;
1191
+ }
1129
1192
  }
1130
1193
 
1131
- return loose_commit(&file, ref);
1194
+ return loose_commit(file, ref);
1132
1195
 
1133
1196
  on_error:
1134
- git_filebuf_cleanup(&file);
1197
+ git_filebuf_cleanup(file);
1135
1198
  return error;
1136
1199
  }
1137
1200
 
@@ -1141,17 +1204,29 @@ static int refdb_fs_backend__delete(
1141
1204
  const git_oid *old_id, const char *old_target)
1142
1205
  {
1143
1206
  refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
1144
- git_buf loose_path = GIT_BUF_INIT;
1145
- size_t pack_pos;
1146
1207
  git_filebuf file = GIT_FILEBUF_INIT;
1147
- int error = 0, cmp = 0;
1148
- bool loose_deleted = 0;
1208
+ int error = 0;
1149
1209
 
1150
1210
  assert(backend && ref_name);
1151
1211
 
1152
1212
  if ((error = loose_lock(&file, backend, ref_name)) < 0)
1153
1213
  return error;
1154
1214
 
1215
+ return refdb_fs_backend__delete_tail(_backend, &file, ref_name, old_id, old_target);
1216
+ }
1217
+
1218
+ static int refdb_fs_backend__delete_tail(
1219
+ git_refdb_backend *_backend,
1220
+ git_filebuf *file,
1221
+ const char *ref_name,
1222
+ const git_oid *old_id, const char *old_target)
1223
+ {
1224
+ refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
1225
+ git_buf loose_path = GIT_BUF_INIT;
1226
+ size_t pack_pos;
1227
+ int error = 0, cmp = 0;
1228
+ bool loose_deleted = 0;
1229
+
1155
1230
  error = cmp_old_ref(&cmp, _backend, ref_name, old_id, old_target);
1156
1231
  if (error < 0)
1157
1232
  goto cleanup;
@@ -1197,7 +1272,7 @@ static int refdb_fs_backend__delete(
1197
1272
  error = packed_write(backend);
1198
1273
 
1199
1274
  cleanup:
1200
- git_filebuf_cleanup(&file);
1275
+ git_filebuf_cleanup(file);
1201
1276
 
1202
1277
  return error;
1203
1278
  }
@@ -1578,11 +1653,6 @@ static int lock_reflog(git_filebuf *file, refdb_fs_backend *backend, const char
1578
1653
 
1579
1654
  repo = backend->repo;
1580
1655
 
1581
- if (!git_path_isvalid(backend->repo, refname, GIT_PATH_REJECT_DEFAULTS)) {
1582
- giterr_set(GITERR_INVALID, "Invalid reference name '%s'.", refname);
1583
- return GIT_EINVALIDSPEC;
1584
- }
1585
-
1586
1656
  if (retrieve_reflog_path(&log_path, repo, refname) < 0)
1587
1657
  return -1;
1588
1658
 
@@ -1847,6 +1917,8 @@ int git_refdb_backend_fs(
1847
1917
  backend->parent.del = &refdb_fs_backend__delete;
1848
1918
  backend->parent.rename = &refdb_fs_backend__rename;
1849
1919
  backend->parent.compress = &refdb_fs_backend__compress;
1920
+ backend->parent.lock = &refdb_fs_backend__lock;
1921
+ backend->parent.unlock = &refdb_fs_backend__unlock;
1850
1922
  backend->parent.has_log = &refdb_reflog_fs__has_log;
1851
1923
  backend->parent.ensure_log = &refdb_reflog_fs__ensure_log;
1852
1924
  backend->parent.free = &refdb_fs_backend__free;
@@ -148,7 +148,7 @@ size_t git_reflog_entrycount(git_reflog *reflog)
148
148
  return reflog->entries.length;
149
149
  }
150
150
 
151
- const git_reflog_entry * git_reflog_entry_byindex(git_reflog *reflog, size_t idx)
151
+ const git_reflog_entry * git_reflog_entry_byindex(const git_reflog *reflog, size_t idx)
152
152
  {
153
153
  assert(reflog);
154
154
 
@@ -22,6 +22,7 @@
22
22
  #include <git2/refdb.h>
23
23
  #include <git2/sys/refs.h>
24
24
  #include <git2/signature.h>
25
+ #include <git2/commit.h>
25
26
 
26
27
  GIT__USE_STRMAP;
27
28
 
@@ -411,7 +412,7 @@ static int reference__create(
411
412
  return 0;
412
413
  }
413
414
 
414
- static int log_signature(git_signature **out, git_repository *repo)
415
+ int git_reference__log_signature(git_signature **out, git_repository *repo)
415
416
  {
416
417
  int error;
417
418
  git_signature *who;
@@ -441,7 +442,7 @@ int git_reference_create_matching(
441
442
  assert(id);
442
443
 
443
444
  if (!signature) {
444
- if ((error = log_signature(&who, repo)) < 0)
445
+ if ((error = git_reference__log_signature(&who, repo)) < 0)
445
446
  return error;
446
447
  else
447
448
  signature = who;
@@ -482,7 +483,7 @@ int git_reference_symbolic_create_matching(
482
483
  assert(target);
483
484
 
484
485
  if (!signature) {
485
- if ((error = log_signature(&who, repo)) < 0)
486
+ if ((error = git_reference__log_signature(&who, repo)) < 0)
486
487
  return error;
487
488
  else
488
489
  signature = who;
@@ -1090,6 +1091,40 @@ int git_reference__update_terminal(
1090
1091
  return reference__update_terminal(repo, ref_name, oid, 0, signature, log_message);
1091
1092
  }
1092
1093
 
1094
+ int git_reference__update_for_commit(
1095
+ git_repository *repo,
1096
+ git_reference *ref,
1097
+ const char *ref_name,
1098
+ const git_oid *id,
1099
+ const git_signature *committer,
1100
+ const char *operation)
1101
+ {
1102
+ git_reference *ref_new = NULL;
1103
+ git_commit *commit = NULL;
1104
+ git_buf reflog_msg = GIT_BUF_INIT;
1105
+ int error;
1106
+
1107
+ if ((error = git_commit_lookup(&commit, repo, id)) < 0 ||
1108
+ (error = git_buf_printf(&reflog_msg, "%s%s: %s",
1109
+ operation ? operation : "commit",
1110
+ git_commit_parentcount(commit) == 0 ? " (initial)" : "",
1111
+ git_commit_summary(commit))) < 0)
1112
+ goto done;
1113
+
1114
+ if (ref)
1115
+ error = git_reference_set_target(
1116
+ &ref_new, ref, id, committer, git_buf_cstr(&reflog_msg));
1117
+ else
1118
+ error = git_reference__update_terminal(
1119
+ repo, ref_name, id, committer, git_buf_cstr(&reflog_msg));
1120
+
1121
+ done:
1122
+ git_reference_free(ref_new);
1123
+ git_buf_free(&reflog_msg);
1124
+ git_commit_free(commit);
1125
+ return error;
1126
+ }
1127
+
1093
1128
  int git_reference_has_log(git_repository *repo, const char *refname)
1094
1129
  {
1095
1130
  int error;
@@ -35,7 +35,7 @@
35
35
  #define GIT_FETCH_HEAD_FILE "FETCH_HEAD"
36
36
  #define GIT_MERGE_HEAD_FILE "MERGE_HEAD"
37
37
  #define GIT_REVERT_HEAD_FILE "REVERT_HEAD"
38
- #define GIT_CHERRY_PICK_HEAD_FILE "CHERRY_PICK_HEAD"
38
+ #define GIT_CHERRYPICK_HEAD_FILE "CHERRY_PICK_HEAD"
39
39
  #define GIT_BISECT_LOG_FILE "BISECT_LOG"
40
40
  #define GIT_REBASE_MERGE_DIR "rebase-merge/"
41
41
  #define GIT_REBASE_MERGE_INTERACTIVE_FILE GIT_REBASE_MERGE_DIR "interactive"
@@ -63,7 +63,7 @@ struct git_reference {
63
63
  } target;
64
64
 
65
65
  git_oid peel;
66
- char name[0];
66
+ char name[GIT_FLEX_ARRAY];
67
67
  };
68
68
 
69
69
  git_reference *git_reference__set_name(git_reference *ref, const char *name);
@@ -98,4 +98,15 @@ int git_reference_lookup_resolved(
98
98
  const char *name,
99
99
  int max_deref);
100
100
 
101
+ int git_reference__log_signature(git_signature **out, git_repository *repo);
102
+
103
+ /** Update a reference after a commit. */
104
+ int git_reference__update_for_commit(
105
+ git_repository *repo,
106
+ git_reference *ref,
107
+ const char *ref_name,
108
+ const git_oid *id,
109
+ const git_signature *committer,
110
+ const char *operation);
111
+
101
112
  #endif
@@ -119,6 +119,12 @@ int git_refspec__parse(git_refspec *refspec, const char *input, bool is_fetch)
119
119
  if (!git_reference__is_valid_name(refspec->dst, flags))
120
120
  goto invalid;
121
121
  }
122
+
123
+ /* if the RHS is empty, then it's a copy of the LHS */
124
+ if (!refspec->dst) {
125
+ refspec->dst = git__strdup(refspec->src);
126
+ GITERR_CHECK_ALLOC(refspec->dst);
127
+ }
122
128
  }
123
129
 
124
130
  refspec->string = git__strdup(input);
@@ -223,7 +229,13 @@ static int refspec_transform(
223
229
 
224
230
  int git_refspec_transform(git_buf *out, const git_refspec *spec, const char *name)
225
231
  {
226
- git_buf_sanitize(out);
232
+ assert(out && spec && name);
233
+ git_buf_sanitize(out);
234
+
235
+ if (!git_refspec_src_matches(spec, name)) {
236
+ giterr_set(GITERR_INVALID, "ref '%s' doesn't match the source", name);
237
+ return -1;
238
+ }
227
239
 
228
240
  if (!spec->pattern)
229
241
  return git_buf_puts(out, spec->dst);
@@ -233,7 +245,13 @@ int git_refspec_transform(git_buf *out, const git_refspec *spec, const char *nam
233
245
 
234
246
  int git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name)
235
247
  {
236
- git_buf_sanitize(out);
248
+ assert(out && spec && name);
249
+ git_buf_sanitize(out);
250
+
251
+ if (!git_refspec_dst_matches(spec, name)) {
252
+ giterr_set(GITERR_INVALID, "ref '%s' doesn't match the destination", name);
253
+ return -1;
254
+ }
237
255
 
238
256
  if (!spec->pattern)
239
257
  return git_buf_puts(out, spec->src);
@@ -21,7 +21,7 @@
21
21
 
22
22
  static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs);
23
23
 
24
- static int add_refspec(git_remote *remote, const char *string, bool is_fetch)
24
+ static int add_refspec_to(git_vector *vector, const char *string, bool is_fetch)
25
25
  {
26
26
  git_refspec *spec;
27
27
 
@@ -34,7 +34,7 @@ static int add_refspec(git_remote *remote, const char *string, bool is_fetch)
34
34
  }
35
35
 
36
36
  spec->push = !is_fetch;
37
- if (git_vector_insert(&remote->refspecs, spec) < 0) {
37
+ if (git_vector_insert(vector, spec) < 0) {
38
38
  git_refspec__free(spec);
39
39
  git__free(spec);
40
40
  return -1;
@@ -43,6 +43,11 @@ static int add_refspec(git_remote *remote, const char *string, bool is_fetch)
43
43
  return 0;
44
44
  }
45
45
 
46
+ static int add_refspec(git_remote *remote, const char *string, bool is_fetch)
47
+ {
48
+ return add_refspec_to(&remote->refspecs, string, is_fetch);
49
+ }
50
+
46
51
  static int download_tags_value(git_remote *remote, git_config *cfg)
47
52
  {
48
53
  const git_config_entry *ce;
@@ -80,6 +85,8 @@ static int ensure_remote_name_is_valid(const char *name)
80
85
  return error;
81
86
  }
82
87
 
88
+ #if 0
89
+ /* We could export this as a helper */
83
90
  static int get_check_cert(int *out, git_repository *repo)
84
91
  {
85
92
  git_config *cfg;
@@ -105,11 +112,32 @@ static int get_check_cert(int *out, git_repository *repo)
105
112
  *out = git_config__get_bool_force(cfg, "http.sslverify", 1);
106
113
  return 0;
107
114
  }
115
+ #endif
116
+
117
+ static int canonicalize_url(git_buf *out, const char *in)
118
+ {
119
+ #ifdef GIT_WIN32
120
+ const char *c;
121
+
122
+ /* Given a UNC path like \\server\path, we need to convert this
123
+ * to //server/path for compatibility with core git.
124
+ */
125
+ if (in[0] == '\\' && in[1] == '\\' &&
126
+ (git__isalpha(in[2]) || git__isdigit(in[2]))) {
127
+ for (c = in; *c; c++)
128
+ git_buf_putc(out, *c == '\\' ? '/' : *c);
129
+
130
+ return git_buf_oom(out) ? -1 : 0;
131
+ }
132
+ #endif
133
+
134
+ return git_buf_puts(out, in);
135
+ }
108
136
 
109
137
  static int create_internal(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
110
138
  {
111
139
  git_remote *remote;
112
- git_buf fetchbuf = GIT_BUF_INIT;
140
+ git_buf canonical_url = GIT_BUF_INIT, fetchbuf = GIT_BUF_INIT;
113
141
  int error = -1;
114
142
 
115
143
  /* name is optional */
@@ -121,14 +149,11 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n
121
149
  remote->repo = repo;
122
150
  remote->update_fetchhead = 1;
123
151
 
124
- if (get_check_cert(&remote->check_cert, repo) < 0)
152
+ if (git_vector_init(&remote->refs, 32, NULL) < 0 ||
153
+ canonicalize_url(&canonical_url, url) < 0)
125
154
  goto on_error;
126
155
 
127
- if (git_vector_init(&remote->refs, 32, NULL) < 0)
128
- goto on_error;
129
-
130
- remote->url = git__strdup(url);
131
- GITERR_CHECK_ALLOC(remote->url);
156
+ remote->url = git_buf_detach(&canonical_url);
132
157
 
133
158
  if (name != NULL) {
134
159
  remote->name = git__strdup(name);
@@ -138,6 +163,10 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n
138
163
  if (fetch != NULL) {
139
164
  if (add_refspec(remote, fetch, true) < 0)
140
165
  goto on_error;
166
+
167
+ /* Move the data over to where the matching functions can find them */
168
+ if (dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs) < 0)
169
+ goto on_error;
141
170
  }
142
171
 
143
172
  if (!name)
@@ -146,11 +175,13 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n
146
175
 
147
176
  *out = remote;
148
177
  git_buf_free(&fetchbuf);
178
+ git_buf_free(&canonical_url);
149
179
  return 0;
150
180
 
151
181
  on_error:
152
182
  git_remote_free(remote);
153
183
  git_buf_free(&fetchbuf);
184
+ git_buf_free(&canonical_url);
154
185
  return error;
155
186
  }
156
187
 
@@ -159,7 +190,7 @@ static int ensure_remote_doesnot_exist(git_repository *repo, const char *name)
159
190
  int error;
160
191
  git_remote *remote;
161
192
 
162
- error = git_remote_load(&remote, repo, name);
193
+ error = git_remote_lookup(&remote, repo, name);
163
194
 
164
195
  if (error == GIT_ENOTFOUND)
165
196
  return 0;
@@ -180,34 +211,15 @@ static int ensure_remote_doesnot_exist(git_repository *repo, const char *name)
180
211
  int git_remote_create(git_remote **out, git_repository *repo, const char *name, const char *url)
181
212
  {
182
213
  git_buf buf = GIT_BUF_INIT;
183
- git_remote *remote = NULL;
184
214
  int error;
185
215
 
186
- if ((error = ensure_remote_name_is_valid(name)) < 0)
187
- return error;
188
-
189
- if ((error = ensure_remote_doesnot_exist(repo, name)) < 0)
190
- return error;
191
-
192
216
  if (git_buf_printf(&buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0)
193
217
  return -1;
194
218
 
195
- if (create_internal(&remote, repo, name, url, git_buf_cstr(&buf)) < 0)
196
- goto on_error;
197
-
219
+ error = git_remote_create_with_fetchspec(out, repo, name, url, git_buf_cstr(&buf));
198
220
  git_buf_free(&buf);
199
221
 
200
- if (git_remote_save(remote) < 0)
201
- goto on_error;
202
-
203
- *out = remote;
204
-
205
- return 0;
206
-
207
- on_error:
208
- git_buf_free(&buf);
209
- git_remote_free(remote);
210
- return -1;
222
+ return error;
211
223
  }
212
224
 
213
225
  int git_remote_create_with_fetchspec(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
@@ -267,12 +279,13 @@ int git_remote_dup(git_remote **dest, git_remote *source)
267
279
 
268
280
  if (source->pushurl != NULL) {
269
281
  remote->pushurl = git__strdup(source->pushurl);
270
- GITERR_CHECK_ALLOC(remote->pushurl);
282
+ GITERR_CHECK_ALLOC(remote->pushurl);
271
283
  }
272
284
 
285
+ remote->transport_cb = source->transport_cb;
286
+ remote->transport_cb_payload = source->transport_cb_payload;
273
287
  remote->repo = source->repo;
274
288
  remote->download_tags = source->download_tags;
275
- remote->check_cert = source->check_cert;
276
289
  remote->update_fetchhead = source->update_fetchhead;
277
290
 
278
291
  if (git_vector_init(&remote->refs, 32, NULL) < 0 ||
@@ -341,7 +354,7 @@ static int get_optional_config(
341
354
  return error;
342
355
  }
343
356
 
344
- int git_remote_load(git_remote **out, git_repository *repo, const char *name)
357
+ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
345
358
  {
346
359
  git_remote *remote;
347
360
  git_buf buf = GIT_BUF_INIT;
@@ -367,11 +380,9 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
367
380
  remote->name = git__strdup(name);
368
381
  GITERR_CHECK_ALLOC(remote->name);
369
382
 
370
- if ((error = get_check_cert(&remote->check_cert, repo)) < 0)
371
- goto cleanup;
372
-
373
383
  if (git_vector_init(&remote->refs, 32, NULL) < 0 ||
374
384
  git_vector_init(&remote->refspecs, 2, NULL) < 0 ||
385
+ git_vector_init(&remote->passive_refspecs, 2, NULL) < 0 ||
375
386
  git_vector_init(&remote->active_refspecs, 2, NULL) < 0) {
376
387
  error = -1;
377
388
  goto cleanup;
@@ -659,18 +670,21 @@ int git_remote_connect(git_remote *remote, git_direction direction)
659
670
  return -1;
660
671
  }
661
672
 
662
- /* A transport could have been supplied in advance with
663
- * git_remote_set_transport */
673
+ /* If we don't have a transport object yet, and the caller specified a
674
+ * custom transport factory, use that */
675
+ if (!t && remote->transport_cb &&
676
+ (error = remote->transport_cb(&t, remote, remote->transport_cb_payload)) < 0)
677
+ return error;
678
+
679
+ /* If we still don't have a transport, then use the global
680
+ * transport registrations which map URI schemes to transport factories */
664
681
  if (!t && (error = git_transport_new(&t, remote, url)) < 0)
665
682
  return error;
666
683
 
667
684
  if (t->set_callbacks &&
668
- (error = t->set_callbacks(t, remote->callbacks.sideband_progress, NULL, remote->callbacks.payload)) < 0)
685
+ (error = t->set_callbacks(t, remote->callbacks.sideband_progress, NULL, remote->callbacks.certificate_check, remote->callbacks.payload)) < 0)
669
686
  goto on_error;
670
687
 
671
- if (!remote->check_cert)
672
- flags |= GIT_TRANSPORTFLAGS_NO_CHECK_CERT;
673
-
674
688
  if ((error = t->connect(t, url, remote->callbacks.credentials, remote->callbacks.payload, direction, flags)) != 0)
675
689
  goto on_error;
676
690
 
@@ -812,20 +826,43 @@ static int ls_to_vector(git_vector *out, git_remote *remote)
812
826
  return 0;
813
827
  }
814
828
 
815
- int git_remote_download(git_remote *remote)
829
+ int git_remote_download(git_remote *remote, const git_strarray *refspecs)
816
830
  {
817
- int error;
818
- git_vector refs;
831
+ int error = -1;
832
+ size_t i;
833
+ git_vector refs, specs, *to_active;
819
834
 
820
835
  assert(remote);
821
836
 
822
837
  if (ls_to_vector(&refs, remote) < 0)
823
838
  return -1;
824
839
 
840
+ if ((git_vector_init(&specs, 0, NULL)) < 0)
841
+ goto on_error;
842
+
843
+ remote->passed_refspecs = 0;
844
+ if (!refspecs || !refspecs->count) {
845
+ to_active = &remote->refspecs;
846
+ } else {
847
+ for (i = 0; i < refspecs->count; i++) {
848
+ if ((error = add_refspec_to(&specs, refspecs->strings[i], true)) < 0)
849
+ goto on_error;
850
+ }
851
+
852
+ to_active = &specs;
853
+ remote->passed_refspecs = 1;
854
+ }
855
+
856
+ free_refspecs(&remote->passive_refspecs);
857
+ if ((error = dwim_refspecs(&remote->passive_refspecs, &remote->refspecs, &refs)) < 0)
858
+ goto on_error;
859
+
825
860
  free_refspecs(&remote->active_refspecs);
861
+ error = dwim_refspecs(&remote->active_refspecs, to_active, &refs);
826
862
 
827
- error = dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &refs);
828
863
  git_vector_free(&refs);
864
+ free_refspecs(&specs);
865
+ git_vector_free(&specs);
829
866
 
830
867
  if (error < 0)
831
868
  return error;
@@ -834,10 +871,17 @@ int git_remote_download(git_remote *remote)
834
871
  return error;
835
872
 
836
873
  return git_fetch_download_pack(remote);
874
+
875
+ on_error:
876
+ git_vector_free(&refs);
877
+ free_refspecs(&specs);
878
+ git_vector_free(&specs);
879
+ return error;
837
880
  }
838
881
 
839
882
  int git_remote_fetch(
840
883
  git_remote *remote,
884
+ const git_strarray *refspecs,
841
885
  const git_signature *signature,
842
886
  const char *reflog_message)
843
887
  {
@@ -848,7 +892,7 @@ int git_remote_fetch(
848
892
  if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH)) != 0)
849
893
  return error;
850
894
 
851
- error = git_remote_download(remote);
895
+ error = git_remote_download(remote, refspecs);
852
896
 
853
897
  /* We don't need to be connected anymore */
854
898
  git_remote_disconnect(remote);
@@ -890,21 +934,50 @@ static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *upda
890
934
  return 0;
891
935
  }
892
936
 
893
- static int remote_head_for_ref(git_remote_head **out, git_refspec *spec, git_vector *update_heads, git_reference *ref)
937
+ static int ref_to_update(int *update, git_buf *remote_name, git_remote *remote, git_refspec *spec, const char *ref_name)
938
+ {
939
+ int error = 0;
940
+ git_repository *repo;
941
+ git_buf upstream_remote = GIT_BUF_INIT;
942
+ git_buf upstream_name = GIT_BUF_INIT;
943
+
944
+ repo = git_remote_owner(remote);
945
+
946
+ if ((!git_reference__is_branch(ref_name)) ||
947
+ !git_remote_name(remote) ||
948
+ (error = git_branch_upstream_remote(&upstream_remote, repo, ref_name) < 0) ||
949
+ git__strcmp(git_remote_name(remote), git_buf_cstr(&upstream_remote)) ||
950
+ (error = git_branch_upstream_name(&upstream_name, repo, ref_name)) < 0 ||
951
+ !git_refspec_dst_matches(spec, git_buf_cstr(&upstream_name)) ||
952
+ (error = git_refspec_rtransform(remote_name, spec, upstream_name.ptr)) < 0) {
953
+ /* Not an error if there is no upstream */
954
+ if (error == GIT_ENOTFOUND) {
955
+ giterr_clear();
956
+ error = 0;
957
+ }
958
+
959
+ *update = 0;
960
+ } else {
961
+ *update = 1;
962
+ }
963
+
964
+ git_buf_free(&upstream_remote);
965
+ git_buf_free(&upstream_name);
966
+ return error;
967
+ }
968
+
969
+ static int remote_head_for_ref(git_remote_head **out, git_remote *remote, git_refspec *spec, git_vector *update_heads, git_reference *ref)
894
970
  {
895
971
  git_reference *resolved_ref = NULL;
896
972
  git_buf remote_name = GIT_BUF_INIT;
897
- git_buf upstream_name = GIT_BUF_INIT;
898
- git_repository *repo;
973
+ git_config *config = NULL;
899
974
  const char *ref_name;
900
- int error = 0;
975
+ int error = 0, update;
901
976
 
902
977
  assert(out && spec && ref);
903
978
 
904
979
  *out = NULL;
905
980
 
906
- repo = git_reference_owner(ref);
907
-
908
981
  error = git_reference_resolve(&resolved_ref, ref);
909
982
 
910
983
  /* If we're in an unborn branch, let's pretend nothing happened */
@@ -915,22 +988,15 @@ static int remote_head_for_ref(git_remote_head **out, git_refspec *spec, git_vec
915
988
  ref_name = git_reference_name(resolved_ref);
916
989
  }
917
990
 
918
- if ((!git_reference__is_branch(ref_name)) ||
919
- (error = git_branch_upstream_name(&upstream_name, repo, ref_name)) < 0 ||
920
- (error = git_refspec_rtransform(&remote_name, spec, upstream_name.ptr)) < 0) {
921
- /* Not an error if there is no upstream */
922
- if (error == GIT_ENOTFOUND)
923
- error = 0;
924
-
991
+ if ((error = ref_to_update(&update, &remote_name, remote, spec, ref_name)) < 0)
925
992
  goto cleanup;
926
- }
927
993
 
928
- error = remote_head_for_fetchspec_src(out, update_heads, git_buf_cstr(&remote_name));
994
+ if (update)
995
+ error = remote_head_for_fetchspec_src(out, update_heads, git_buf_cstr(&remote_name));
929
996
 
930
997
  cleanup:
931
998
  git_reference_free(resolved_ref);
932
- git_buf_free(&remote_name);
933
- git_buf_free(&upstream_name);
999
+ git_config_free(config);
934
1000
  return error;
935
1001
  }
936
1002
 
@@ -959,7 +1025,7 @@ static int git_remote_write_fetchhead(git_remote *remote, git_refspec *spec, git
959
1025
  /* Determine what to merge: if refspec was a wildcard, just use HEAD */
960
1026
  if (git_refspec_is_wildcard(spec)) {
961
1027
  if ((error = git_reference_lookup(&head_ref, remote->repo, GIT_HEAD_FILE)) < 0 ||
962
- (error = remote_head_for_ref(&merge_remote_ref, spec, update_heads, head_ref)) < 0)
1028
+ (error = remote_head_for_ref(&merge_remote_ref, remote, spec, update_heads, head_ref)) < 0)
963
1029
  goto cleanup;
964
1030
  } else {
965
1031
  /* If we're fetching a single refspec, that's the only thing that should be in FETCH_HEAD. */
@@ -1036,24 +1102,26 @@ static int update_tips_for_spec(
1036
1102
  if (!git_reference_is_valid_name(head->name))
1037
1103
  continue;
1038
1104
 
1039
- if (git_refspec_src_matches(spec, head->name) && spec->dst) {
1040
- if (git_refspec_transform(&refname, spec, head->name) < 0)
1041
- goto on_error;
1042
- } else if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
1105
+ if (git_refspec_src_matches(&tagspec, head->name)) {
1106
+ if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
1043
1107
 
1044
- if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_ALL)
1045
- autotag = 1;
1108
+ if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_AUTO)
1109
+ autotag = 1;
1046
1110
 
1047
- if (!git_refspec_src_matches(&tagspec, head->name))
1111
+ git_buf_clear(&refname);
1112
+ if (git_buf_puts(&refname, head->name) < 0)
1113
+ goto on_error;
1114
+ } else {
1048
1115
  continue;
1049
-
1050
- git_buf_clear(&refname);
1051
- if (git_buf_puts(&refname, head->name) < 0)
1116
+ }
1117
+ } else if (git_refspec_src_matches(spec, head->name) && spec->dst) {
1118
+ if (git_refspec_transform(&refname, spec, head->name) < 0)
1052
1119
  goto on_error;
1053
1120
  } else {
1054
1121
  continue;
1055
1122
  }
1056
1123
 
1124
+ /* In autotag mode, only create tags for objects already in db */
1057
1125
  if (autotag && !git_odb_exists(odb, &head->oid))
1058
1126
  continue;
1059
1127
 
@@ -1105,6 +1173,97 @@ on_error:
1105
1173
 
1106
1174
  }
1107
1175
 
1176
+ /**
1177
+ * Iteration over the three vectors, with a pause whenever we find a match
1178
+ *
1179
+ * On each stop, we store the iteration stat in the inout i,j,k
1180
+ * parameters, and return the currently matching passive refspec as
1181
+ * well as the head which we matched.
1182
+ */
1183
+ static int next_head(const git_remote *remote, git_vector *refs,
1184
+ git_refspec **out_spec, git_remote_head **out_head,
1185
+ size_t *out_i, size_t *out_j, size_t *out_k)
1186
+ {
1187
+ const git_vector *active, *passive;
1188
+ git_remote_head *head;
1189
+ git_refspec *spec, *passive_spec;
1190
+ size_t i, j, k;
1191
+
1192
+ active = &remote->active_refspecs;
1193
+ passive = &remote->passive_refspecs;
1194
+
1195
+ i = *out_i;
1196
+ j = *out_j;
1197
+ k = *out_k;
1198
+
1199
+ for (; i < refs->length; i++) {
1200
+ head = git_vector_get(refs, i);
1201
+
1202
+ if (!git_reference_is_valid_name(head->name))
1203
+ continue;
1204
+
1205
+ for (; j < active->length; j++) {
1206
+ spec = git_vector_get(active, j);
1207
+
1208
+ if (!git_refspec_src_matches(spec, head->name))
1209
+ continue;
1210
+
1211
+ for (; k < passive->length; k++) {
1212
+ passive_spec = git_vector_get(passive, k);
1213
+
1214
+ if (!git_refspec_src_matches(passive_spec, head->name))
1215
+ continue;
1216
+
1217
+ *out_spec = passive_spec;
1218
+ *out_head = head;
1219
+ *out_i = i;
1220
+ *out_j = j;
1221
+ *out_k = k + 1;
1222
+ return 0;
1223
+
1224
+ }
1225
+ k = 0;
1226
+ }
1227
+ j = 0;
1228
+ }
1229
+
1230
+ return GIT_ITEROVER;
1231
+ }
1232
+
1233
+ static int opportunistic_updates(const git_remote *remote, git_vector *refs, const git_signature *sig, const char *msg)
1234
+ {
1235
+ size_t i, j, k;
1236
+ git_refspec *spec;
1237
+ git_remote_head *head;
1238
+ git_reference *ref;
1239
+ git_buf refname = GIT_BUF_INIT;
1240
+ int error;
1241
+
1242
+ i = j = k = 0;
1243
+
1244
+ while ((error = next_head(remote, refs, &spec, &head, &i, &j, &k)) == 0) {
1245
+ /*
1246
+ * If we got here, there is a refspec which was used
1247
+ * for fetching which matches the source of one of the
1248
+ * passive refspecs, so we should update that
1249
+ * remote-tracking branch, but not add it to
1250
+ * FETCH_HEAD
1251
+ */
1252
+
1253
+ if ((error = git_refspec_transform(&refname, spec, head->name)) < 0)
1254
+ return error;
1255
+
1256
+ error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, true, sig, msg);
1257
+ git_buf_free(&refname);
1258
+ git_reference_free(ref);
1259
+
1260
+ if (error < 0)
1261
+ return error;
1262
+ }
1263
+
1264
+ return 0;
1265
+ }
1266
+
1108
1267
  int git_remote_update_tips(
1109
1268
  git_remote *remote,
1110
1269
  const git_signature *signature,
@@ -1123,8 +1282,8 @@ int git_remote_update_tips(
1123
1282
  goto out;
1124
1283
 
1125
1284
  if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) {
1126
- error = update_tips_for_spec(remote, &tagspec, &refs, signature, reflog_message);
1127
- goto out;
1285
+ if ((error = update_tips_for_spec(remote, &tagspec, &refs, signature, reflog_message)) < 0)
1286
+ goto out;
1128
1287
  }
1129
1288
 
1130
1289
  git_vector_foreach(&remote->active_refspecs, i, spec) {
@@ -1135,6 +1294,10 @@ int git_remote_update_tips(
1135
1294
  goto out;
1136
1295
  }
1137
1296
 
1297
+ /* only try to do opportunisitic updates if the refpec lists differ */
1298
+ if (remote->passed_refspecs)
1299
+ error = opportunistic_updates(remote, &refs, signature, reflog_message);
1300
+
1138
1301
  out:
1139
1302
  git_vector_free(&refs);
1140
1303
  git_refspec__free(&tagspec);
@@ -1188,6 +1351,9 @@ void git_remote_free(git_remote *remote)
1188
1351
  free_refspecs(&remote->active_refspecs);
1189
1352
  git_vector_free(&remote->active_refspecs);
1190
1353
 
1354
+ free_refspecs(&remote->passive_refspecs);
1355
+ git_vector_free(&remote->passive_refspecs);
1356
+
1191
1357
  git__free(remote->url);
1192
1358
  git__free(remote->pushurl);
1193
1359
  git__free(remote->name);
@@ -1240,13 +1406,6 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo)
1240
1406
  return 0;
1241
1407
  }
1242
1408
 
1243
- void git_remote_check_cert(git_remote *remote, int check)
1244
- {
1245
- assert(remote);
1246
-
1247
- remote->check_cert = check;
1248
- }
1249
-
1250
1409
  int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks)
1251
1410
  {
1252
1411
  assert(remote && callbacks);
@@ -1259,6 +1418,7 @@ int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *cal
1259
1418
  return remote->transport->set_callbacks(remote->transport,
1260
1419
  remote->callbacks.sideband_progress,
1261
1420
  NULL,
1421
+ remote->callbacks.certificate_check,
1262
1422
  remote->callbacks.payload);
1263
1423
 
1264
1424
  return 0;
@@ -1271,18 +1431,20 @@ const git_remote_callbacks *git_remote_get_callbacks(git_remote *remote)
1271
1431
  return &remote->callbacks;
1272
1432
  }
1273
1433
 
1274
- int git_remote_set_transport(git_remote *remote, git_transport *transport)
1434
+ int git_remote_set_transport(
1435
+ git_remote *remote,
1436
+ git_transport_cb transport_cb,
1437
+ void *payload)
1275
1438
  {
1276
- assert(remote && transport);
1277
-
1278
- GITERR_CHECK_VERSION(transport, GIT_TRANSPORT_VERSION, "git_transport");
1439
+ assert(remote);
1279
1440
 
1280
1441
  if (remote->transport) {
1281
1442
  giterr_set(GITERR_NET, "A transport is already bound to this remote");
1282
1443
  return -1;
1283
1444
  }
1284
1445
 
1285
- remote->transport = transport;
1446
+ remote->transport_cb = transport_cb;
1447
+ remote->transport_cb_payload = payload;
1286
1448
  return 0;
1287
1449
  }
1288
1450
 
@@ -1525,48 +1687,44 @@ static int rename_fetch_refspecs(git_vector *problems, git_remote *remote, const
1525
1687
  return error;
1526
1688
  }
1527
1689
 
1528
- int git_remote_rename(git_strarray *out, git_remote *remote, const char *new_name)
1690
+ int git_remote_rename(git_strarray *out, git_repository *repo, const char *name, const char *new_name)
1529
1691
  {
1530
1692
  int error;
1531
- git_vector problem_refspecs;
1532
- char *tmp, *dup;
1693
+ git_vector problem_refspecs = GIT_VECTOR_INIT;
1694
+ git_remote *remote = NULL;
1533
1695
 
1534
- assert(out && remote && new_name);
1696
+ assert(out && repo && name && new_name);
1535
1697
 
1536
- if (!remote->name) {
1537
- giterr_set(GITERR_INVALID, "Can't rename an anonymous remote.");
1538
- return GIT_EINVALIDSPEC;
1539
- }
1698
+ if ((error = git_remote_lookup(&remote, repo, name)) < 0)
1699
+ return error;
1540
1700
 
1541
1701
  if ((error = ensure_remote_name_is_valid(new_name)) < 0)
1542
- return error;
1702
+ goto cleanup;
1543
1703
 
1544
- if ((error = ensure_remote_doesnot_exist(remote->repo, new_name)) < 0)
1545
- return error;
1704
+ if ((error = ensure_remote_doesnot_exist(repo, new_name)) < 0)
1705
+ goto cleanup;
1546
1706
 
1547
- if ((error = rename_remote_config_section(remote->repo, remote->name, new_name)) < 0)
1548
- return error;
1707
+ if ((error = rename_remote_config_section(repo, name, new_name)) < 0)
1708
+ goto cleanup;
1549
1709
 
1550
- if ((error = update_branch_remote_config_entry(remote->repo, remote->name, new_name)) < 0)
1551
- return error;
1710
+ if ((error = update_branch_remote_config_entry(repo, name, new_name)) < 0)
1711
+ goto cleanup;
1552
1712
 
1553
- if ((error = rename_remote_references(remote->repo, remote->name, new_name)) < 0)
1554
- return error;
1713
+ if ((error = rename_remote_references(repo, name, new_name)) < 0)
1714
+ goto cleanup;
1555
1715
 
1556
1716
  if ((error = rename_fetch_refspecs(&problem_refspecs, remote, new_name)) < 0)
1557
- return error;
1717
+ goto cleanup;
1558
1718
 
1559
1719
  out->count = problem_refspecs.length;
1560
1720
  out->strings = (char **) problem_refspecs.contents;
1561
1721
 
1562
- dup = git__strdup(new_name);
1563
- GITERR_CHECK_ALLOC(dup);
1564
-
1565
- tmp = remote->name;
1566
- remote->name = dup;
1567
- git__free(tmp);
1722
+ cleanup:
1723
+ if (error < 0)
1724
+ git_vector_free(&problem_refspecs);
1568
1725
 
1569
- return 0;
1726
+ git_remote_free(remote);
1727
+ return error;
1570
1728
  }
1571
1729
 
1572
1730
  int git_remote_update_fetchhead(git_remote *remote)
@@ -1643,27 +1801,14 @@ void git_remote_clear_refspecs(git_remote *remote)
1643
1801
  git_vector_clear(&remote->refspecs);
1644
1802
  }
1645
1803
 
1646
- static int add_and_dwim(git_remote *remote, const char *str, int push)
1647
- {
1648
- git_refspec *spec;
1649
- git_vector *vec;
1650
-
1651
- if (add_refspec(remote, str, !push) < 0)
1652
- return -1;
1653
-
1654
- vec = &remote->refspecs;
1655
- spec = git_vector_get(vec, vec->length - 1);
1656
- return git_refspec__dwim_one(&remote->active_refspecs, spec, &remote->refs);
1657
- }
1658
-
1659
1804
  int git_remote_add_fetch(git_remote *remote, const char *refspec)
1660
1805
  {
1661
- return add_and_dwim(remote, refspec, false);
1806
+ return add_refspec(remote, refspec, true);
1662
1807
  }
1663
1808
 
1664
1809
  int git_remote_add_push(git_remote *remote, const char *refspec)
1665
1810
  {
1666
- return add_and_dwim(remote, refspec, true);
1811
+ return add_refspec(remote, refspec, false);
1667
1812
  }
1668
1813
 
1669
1814
  static int set_refspecs(git_remote *remote, git_strarray *array, int push)
@@ -1691,10 +1836,7 @@ static int set_refspecs(git_remote *remote, git_strarray *array, int push)
1691
1836
  return -1;
1692
1837
  }
1693
1838
 
1694
- free_refspecs(&remote->active_refspecs);
1695
- git_vector_clear(&remote->active_refspecs);
1696
-
1697
- return dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs);
1839
+ return 0;
1698
1840
  }
1699
1841
 
1700
1842
  int git_remote_set_fetch_refspecs(git_remote *remote, git_strarray *array)
@@ -1886,7 +2028,7 @@ static int remove_remote_tracking(git_repository *repo, const char *remote_name)
1886
2028
  size_t i, count;
1887
2029
 
1888
2030
  /* we want to use what's on the config, regardless of changes to the instance in memory */
1889
- if ((error = git_remote_load(&remote, repo, remote_name)) < 0)
2031
+ if ((error = git_remote_lookup(&remote, repo, remote_name)) < 0)
1890
2032
  return error;
1891
2033
 
1892
2034
  count = git_remote_refspec_count(remote);
@@ -1905,29 +2047,15 @@ static int remove_remote_tracking(git_repository *repo, const char *remote_name)
1905
2047
  return error;
1906
2048
  }
1907
2049
 
1908
- int git_remote_delete(git_remote *remote)
2050
+ int git_remote_delete(git_repository *repo, const char *name)
1909
2051
  {
1910
2052
  int error;
1911
- git_repository *repo;
1912
2053
 
1913
- assert(remote);
2054
+ assert(repo && name);
1914
2055
 
1915
- if (!remote->name) {
1916
- giterr_set(GITERR_INVALID, "Can't delete an anonymous remote.");
1917
- return -1;
1918
- }
1919
-
1920
- repo = git_remote_owner(remote);
1921
-
1922
- if ((error = remove_branch_config_related_entries(repo,
1923
- git_remote_name(remote))) < 0)
1924
- return error;
1925
-
1926
- if ((error = remove_remote_tracking(repo, git_remote_name(remote))) < 0)
1927
- return error;
1928
-
1929
- if ((error = rename_remote_config_section(
1930
- repo, git_remote_name(remote), NULL)) < 0)
2056
+ if ((error = remove_branch_config_related_entries(repo, name)) < 0 ||
2057
+ (error = remove_remote_tracking(repo, name)) < 0 ||
2058
+ (error = rename_remote_config_section(repo, name, NULL)) < 0)
1931
2059
  return error;
1932
2060
 
1933
2061
  return 0;
@@ -1949,6 +2077,9 @@ int git_remote_default_branch(git_buf *out, git_remote *remote)
1949
2077
  if (heads_len == 0)
1950
2078
  return GIT_ENOTFOUND;
1951
2079
 
2080
+ if (strcmp(heads[0]->name, GIT_HEAD_FILE))
2081
+ return GIT_ENOTFOUND;
2082
+
1952
2083
  git_buf_sanitize(out);
1953
2084
  /* the first one must be HEAD so if that has the symref info, we're done */
1954
2085
  if (heads[0]->symref_target)
@@ -1965,6 +2096,9 @@ int git_remote_default_branch(git_buf *out, git_remote *remote)
1965
2096
  if (git_oid_cmp(head_id, &heads[i]->oid))
1966
2097
  continue;
1967
2098
 
2099
+ if (git__prefixcmp(heads[i]->name, GIT_REFS_HEADS_DIR))
2100
+ continue;
2101
+
1968
2102
  if (!guess) {
1969
2103
  guess = heads[i];
1970
2104
  continue;