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
@@ -128,6 +128,14 @@ GIT_INLINE(int) git_path_is_relative(const char *p)
128
128
  return (p[0] == '.' && (p[1] == '/' || (p[1] == '.' && p[2] == '/')));
129
129
  }
130
130
 
131
+ /**
132
+ * Check if string is at end of path segment (i.e. looking at '/' or '\0')
133
+ */
134
+ GIT_INLINE(int) git_path_at_end_of_segment(const char *p)
135
+ {
136
+ return !*p || *p == '/';
137
+ }
138
+
131
139
  extern int git__percent_decode(git_buf *decoded_out, const char *input);
132
140
 
133
141
  /**
@@ -188,6 +196,17 @@ extern bool git_path_contains(git_buf *dir, const char *item);
188
196
  */
189
197
  extern bool git_path_contains_dir(git_buf *parent, const char *subdir);
190
198
 
199
+ /**
200
+ * Make the path relative to the given parent path.
201
+ *
202
+ * @param path The path to make relative
203
+ * @param parent The parent path to make path relative to
204
+ * @return 0 if path was made relative, GIT_ENOTFOUND
205
+ * if there was not common root between the paths,
206
+ * or <0.
207
+ */
208
+ extern int git_path_make_relative(git_buf *path, const char *parent);
209
+
191
210
  /**
192
211
  * Check if the given path contains the given file.
193
212
  *
@@ -304,7 +323,7 @@ extern int git_path_cmp(
304
323
  extern int git_path_walk_up(
305
324
  git_buf *pathbuf,
306
325
  const char *ceiling,
307
- int (*callback)(void *payload, git_buf *path),
326
+ int (*callback)(void *payload, const char *path),
308
327
  void *payload);
309
328
 
310
329
  /**
@@ -440,49 +459,7 @@ extern int git_path_iconv(git_path_iconv_t *ic, char **in, size_t *inlen);
440
459
  extern bool git_path_does_fs_decompose_unicode(const char *root);
441
460
 
442
461
  /* Used for paths to repositories on the filesystem */
462
+ extern bool git_path_is_local_file_url(const char *file_url);
443
463
  extern int git_path_from_url_or_path(git_buf *local_path_out, const char *url_or_path);
444
464
 
445
- /* Flags to determine path validity in `git_path_isvalid` */
446
- #define GIT_PATH_REJECT_TRAVERSAL (1 << 0)
447
- #define GIT_PATH_REJECT_DOT_GIT (1 << 1)
448
- #define GIT_PATH_REJECT_SLASH (1 << 2)
449
- #define GIT_PATH_REJECT_BACKSLASH (1 << 3)
450
- #define GIT_PATH_REJECT_TRAILING_DOT (1 << 4)
451
- #define GIT_PATH_REJECT_TRAILING_SPACE (1 << 5)
452
- #define GIT_PATH_REJECT_TRAILING_COLON (1 << 6)
453
- #define GIT_PATH_REJECT_DOS_PATHS (1 << 7)
454
- #define GIT_PATH_REJECT_NT_CHARS (1 << 8)
455
- #define GIT_PATH_REJECT_DOT_GIT_HFS (1 << 9)
456
- #define GIT_PATH_REJECT_DOT_GIT_NTFS (1 << 10)
457
-
458
- /* Default path safety for writing files to disk: since we use the
459
- * Win32 "File Namespace" APIs ("\\?\") we need to protect from
460
- * paths that the normal Win32 APIs would not write.
461
- */
462
- #ifdef GIT_WIN32
463
- # define GIT_PATH_REJECT_DEFAULTS \
464
- GIT_PATH_REJECT_TRAVERSAL | \
465
- GIT_PATH_REJECT_BACKSLASH | \
466
- GIT_PATH_REJECT_TRAILING_DOT | \
467
- GIT_PATH_REJECT_TRAILING_SPACE | \
468
- GIT_PATH_REJECT_TRAILING_COLON | \
469
- GIT_PATH_REJECT_DOS_PATHS | \
470
- GIT_PATH_REJECT_NT_CHARS
471
- #else
472
- # define GIT_PATH_REJECT_DEFAULTS GIT_PATH_REJECT_TRAVERSAL
473
- #endif
474
-
475
- /*
476
- * Determine whether a path is a valid git path or not - this must not contain
477
- * a '.' or '..' component, or a component that is ".git" (in any case).
478
- *
479
- * `repo` is optional. If specified, it will be used to determine the short
480
- * path name to reject (if `GIT_PATH_REJECT_DOS_SHORTNAME` is specified),
481
- * in addition to the default of "git~1".
482
- */
483
- extern bool git_path_isvalid(
484
- git_repository *repo,
485
- const char *path,
486
- unsigned int flags);
487
-
488
465
  #endif
@@ -524,7 +524,7 @@ int git_pathspec_match_workdir(
524
524
  assert(repo);
525
525
 
526
526
  if (!(error = git_iterator_for_workdir(
527
- &iter, repo, pathspec_match_iter_flags(flags), NULL, NULL))) {
527
+ &iter, repo, NULL, NULL, pathspec_match_iter_flags(flags), NULL, NULL))) {
528
528
 
529
529
  error = pathspec_match_from_iterator(out, iter, flags, ps);
530
530
 
@@ -1,4 +1,5 @@
1
1
  #include "pool.h"
2
+ #include "posix.h"
2
3
  #ifndef GIT_WIN32
3
4
  #include <unistd.h>
4
5
  #endif
@@ -305,17 +306,10 @@ uint32_t git_pool__system_page_size(void)
305
306
  static uint32_t size = 0;
306
307
 
307
308
  if (!size) {
308
- #ifdef GIT_WIN32
309
- SYSTEM_INFO info;
310
- GetSystemInfo(&info);
311
- size = (uint32_t)info.dwPageSize;
312
- #elif defined(__amigaos4__)
313
- size = (uint32_t)4096; /* 4K as there is no global value we can query */
314
- #else
315
- size = (uint32_t)sysconf(_SC_PAGE_SIZE);
316
- #endif
317
-
318
- size -= 2 * sizeof(void *); /* allow space for malloc overhead */
309
+ size_t page_size;
310
+ if (git__page_size(&page_size) < 0)
311
+ page_size = 4096;
312
+ size = page_size - 2 * sizeof(void *); /* allow space for malloc overhead */
319
313
  }
320
314
 
321
315
  return size;
@@ -143,8 +143,6 @@ extern uint32_t git_pool__full_pages(git_pool *pool);
143
143
 
144
144
  extern bool git_pool__ptr_in_pool(git_pool *pool, void *ptr);
145
145
 
146
- extern uint32_t git_pool__system_page_size(void);
147
-
148
146
  extern uint32_t git_pool__suggest_items_per_page(uint32_t item_size);
149
147
 
150
148
  #endif
@@ -151,15 +151,14 @@ int p_rename(const char *from, const char *to)
151
151
 
152
152
  #endif /* GIT_WIN32 */
153
153
 
154
- int p_read(git_file fd, void *buf, size_t cnt)
154
+ ssize_t p_read(git_file fd, void *buf, size_t cnt)
155
155
  {
156
156
  char *b = buf;
157
157
 
158
158
  while (cnt) {
159
159
  ssize_t r;
160
160
  #ifdef GIT_WIN32
161
- assert((size_t)((unsigned int)cnt) == cnt);
162
- r = read(fd, b, (unsigned int)cnt);
161
+ r = read(fd, b, cnt > INT_MAX ? INT_MAX : (unsigned int)cnt);
163
162
  #else
164
163
  r = read(fd, b, cnt);
165
164
  #endif
@@ -173,7 +172,7 @@ int p_read(git_file fd, void *buf, size_t cnt)
173
172
  cnt -= r;
174
173
  b += r;
175
174
  }
176
- return (int)(b - (char *)buf);
175
+ return (b - (char *)buf);
177
176
  }
178
177
 
179
178
  int p_write(git_file fd, const void *buf, size_t cnt)
@@ -207,10 +206,11 @@ int p_write(git_file fd, const void *buf, size_t cnt)
207
206
 
208
207
  #include "map.h"
209
208
 
210
- long git__page_size(void)
209
+ int git__page_size(size_t *page_size)
211
210
  {
212
211
  /* dummy; here we don't need any alignment anyway */
213
- return 4096;
212
+ *page_size = 4096;
213
+ return 0;
214
214
  }
215
215
 
216
216
 
@@ -12,23 +12,61 @@
12
12
  #include <time.h>
13
13
  #include "fnmatch.h"
14
14
 
15
+ /* stat: file mode type testing macros */
15
16
  #ifndef S_IFGITLINK
16
17
  #define S_IFGITLINK 0160000
17
18
  #define S_ISGITLINK(m) (((m) & S_IFMT) == S_IFGITLINK)
18
19
  #endif
19
20
 
21
+ #ifndef S_IFLNK
22
+ #define S_IFLNK 0120000
23
+ #undef _S_IFLNK
24
+ #define _S_IFLNK S_IFLNK
25
+ #endif
26
+
27
+ #ifndef S_IXUSR
28
+ #define S_IXUSR 00100
29
+ #endif
30
+
31
+ #ifndef S_ISLNK
32
+ #define S_ISLNK(m) (((m) & _S_IFMT) == _S_IFLNK)
33
+ #endif
34
+
35
+ #ifndef S_ISDIR
36
+ #define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
37
+ #endif
38
+
39
+ #ifndef S_ISREG
40
+ #define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
41
+ #endif
42
+
43
+ #ifndef S_ISFIFO
44
+ #define S_ISFIFO(m) (((m) & _S_IFMT) == _S_IFIFO)
45
+ #endif
46
+
20
47
  /* if S_ISGID is not defined, then don't try to set it */
21
48
  #ifndef S_ISGID
22
49
  #define S_ISGID 0
23
50
  #endif
24
51
 
25
- #if !defined(O_BINARY)
52
+ #ifndef O_BINARY
26
53
  #define O_BINARY 0
27
54
  #endif
28
- #if !defined(O_CLOEXEC)
55
+ #ifndef O_CLOEXEC
29
56
  #define O_CLOEXEC 0
30
57
  #endif
31
58
 
59
+ /* access() mode parameter #defines */
60
+ #ifndef F_OK
61
+ #define F_OK 0 /* existence check */
62
+ #endif
63
+ #ifndef W_OK
64
+ #define W_OK 2 /* write mode check */
65
+ #endif
66
+ #ifndef R_OK
67
+ #define R_OK 4 /* read mode check */
68
+ #endif
69
+
32
70
  /* Determine whether an errno value indicates that a read or write failed
33
71
  * because the descriptor is blocked.
34
72
  */
@@ -38,6 +76,12 @@
38
76
  #define GIT_ISBLOCKED(e) ((e) == EAGAIN)
39
77
  #endif
40
78
 
79
+ /* define some standard errnos that the runtime may be missing. for example,
80
+ * mingw lacks EAFNOSUPPORT. */
81
+ #ifndef EAFNOSUPPORT
82
+ #define EAFNOSUPPORT (INT_MAX-1)
83
+ #endif
84
+
41
85
  typedef int git_file;
42
86
 
43
87
  /**
@@ -53,11 +97,9 @@ typedef int git_file;
53
97
  * Use your manpages to check the docs on these.
54
98
  */
55
99
 
56
- extern int p_read(git_file fd, void *buf, size_t cnt);
100
+ extern ssize_t p_read(git_file fd, void *buf, size_t cnt);
57
101
  extern int p_write(git_file fd, const void *buf, size_t cnt);
58
102
 
59
- #define p_fstat(f,b) fstat(f, b)
60
- #define p_lseek(f,n,w) lseek(f, n, w)
61
103
  #define p_close(fd) close(fd)
62
104
  #define p_umask(m) umask(m)
63
105
 
@@ -66,29 +108,7 @@ extern int p_creat(const char *path, mode_t mode);
66
108
  extern int p_getcwd(char *buffer_out, size_t size);
67
109
  extern int p_rename(const char *from, const char *to);
68
110
 
69
- #ifndef GIT_WIN32
70
-
71
- #define p_stat(p,b) stat(p, b)
72
- #define p_chdir(p) chdir(p)
73
- #define p_rmdir(p) rmdir(p)
74
- #define p_chmod(p,m) chmod(p, m)
75
- #define p_access(p,m) access(p,m)
76
- #define p_ftruncate(fd, sz) ftruncate(fd, sz)
77
- #define p_recv(s,b,l,f) recv(s,b,l,f)
78
- #define p_send(s,b,l,f) send(s,b,l,f)
79
- typedef int GIT_SOCKET;
80
- #define INVALID_SOCKET -1
81
-
82
- #define p_localtime_r localtime_r
83
- #define p_gmtime_r gmtime_r
84
-
85
- #else
86
-
87
- typedef SOCKET GIT_SOCKET;
88
- extern struct tm * p_localtime_r (const time_t *timer, struct tm *result);
89
- extern struct tm * p_gmtime_r (const time_t *timer, struct tm *result);
90
-
91
- #endif
111
+ extern int git__page_size(size_t *page_size);
92
112
 
93
113
  /**
94
114
  * Platform-dependent methods
@@ -19,7 +19,7 @@ static int push_spec_rref_cmp(const void *a, const void *b)
19
19
  {
20
20
  const push_spec *push_spec_a = a, *push_spec_b = b;
21
21
 
22
- return strcmp(push_spec_a->rref, push_spec_b->rref);
22
+ return strcmp(push_spec_a->refspec.dst, push_spec_b->refspec.dst);
23
23
  }
24
24
 
25
25
  static int push_status_ref_cmp(const void *a, const void *b)
@@ -94,12 +94,7 @@ static void free_refspec(push_spec *spec)
94
94
  if (spec == NULL)
95
95
  return;
96
96
 
97
- if (spec->lref)
98
- git__free(spec->lref);
99
-
100
- if (spec->rref)
101
- git__free(spec->rref);
102
-
97
+ git_refspec__free(&spec->refspec);
103
98
  git__free(spec);
104
99
  }
105
100
 
@@ -134,47 +129,25 @@ static int check_lref(git_push *push, char *ref)
134
129
  static int parse_refspec(git_push *push, push_spec **spec, const char *str)
135
130
  {
136
131
  push_spec *s;
137
- char *delim;
138
132
 
139
133
  *spec = NULL;
140
134
 
141
135
  s = git__calloc(1, sizeof(*s));
142
136
  GITERR_CHECK_ALLOC(s);
143
137
 
144
- if (str[0] == '+') {
145
- s->force = true;
146
- str++;
138
+ if (git_refspec__parse(&s->refspec, str, false) < 0) {
139
+ giterr_set(GITERR_INVALID, "invalid refspec %s", str);
140
+ goto on_error;
147
141
  }
148
142
 
149
- delim = strchr(str, ':');
150
- if (delim == NULL) {
151
- s->lref = git__strdup(str);
152
- if (!s->lref || check_lref(push, s->lref) < 0)
153
- goto on_error;
154
- } else {
155
- if (delim - str) {
156
- s->lref = git__strndup(str, delim - str);
157
- if (!s->lref || check_lref(push, s->lref) < 0)
158
- goto on_error;
159
- }
160
-
161
- if (strlen(delim + 1)) {
162
- s->rref = git__strdup(delim + 1);
163
- if (!s->rref || check_rref(s->rref) < 0)
164
- goto on_error;
165
- }
143
+ if (s->refspec.src && s->refspec.src[0] != '\0' &&
144
+ check_lref(push, s->refspec.src) < 0) {
145
+ goto on_error;
166
146
  }
167
147
 
168
- if (!s->lref && !s->rref)
148
+ if (check_rref(s->refspec.dst) < 0)
169
149
  goto on_error;
170
150
 
171
- /* If rref is ommitted, use the same ref name as lref */
172
- if (!s->rref) {
173
- s->rref = git__strdup(s->lref);
174
- if (!s->rref || check_rref(s->rref) < 0)
175
- goto on_error;
176
- }
177
-
178
151
  *spec = s;
179
152
  return 0;
180
153
 
@@ -220,7 +193,7 @@ int git_push_update_tips(
220
193
 
221
194
  /* Find matching push ref spec */
222
195
  git_vector_foreach(&push->specs, j, push_spec) {
223
- if (!strcmp(push_spec->rref, status->ref))
196
+ if (!strcmp(push_spec->refspec.dst, status->ref))
224
197
  break;
225
198
  }
226
199
 
@@ -353,7 +326,7 @@ static int revwalk(git_vector *commits, git_push *push)
353
326
  } else if (git_revwalk_push(rw, &spec->loid) < 0)
354
327
  goto on_error;
355
328
 
356
- if (!spec->force) {
329
+ if (!spec->refspec.force) {
357
330
  git_oid base;
358
331
 
359
332
  if (git_oid_iszero(&spec->roid))
@@ -571,22 +544,20 @@ static int calculate_work(git_push *push)
571
544
  /* Update local and remote oids*/
572
545
 
573
546
  git_vector_foreach(&push->specs, i, spec) {
574
- if (spec->lref) {
547
+ if (spec->refspec.src && spec->refspec.src[0]!= '\0') {
575
548
  /* This is a create or update. Local ref must exist. */
576
549
  if (git_reference_name_to_id(
577
- &spec->loid, push->repo, spec->lref) < 0) {
578
- giterr_set(GITERR_REFERENCE, "No such reference '%s'", spec->lref);
550
+ &spec->loid, push->repo, spec->refspec.src) < 0) {
551
+ giterr_set(GITERR_REFERENCE, "No such reference '%s'", spec->refspec.src);
579
552
  return -1;
580
553
  }
581
554
  }
582
555
 
583
- if (spec->rref) {
584
- /* Remote ref may or may not (e.g. during create) already exist. */
585
- git_vector_foreach(&push->remote->refs, j, head) {
586
- if (!strcmp(spec->rref, head->name)) {
587
- git_oid_cpy(&spec->roid, &head->oid);
588
- break;
589
- }
556
+ /* Remote ref may or may not (e.g. during create) already exist. */
557
+ git_vector_foreach(&push->remote->refs, j, head) {
558
+ if (!strcmp(spec->refspec.dst, head->name)) {
559
+ git_oid_cpy(&spec->roid, &head->oid);
560
+ break;
590
561
  }
591
562
  }
592
563
  }
@@ -8,15 +8,13 @@
8
8
  #define INCLUDE_push_h__
9
9
 
10
10
  #include "git2.h"
11
+ #include "refspec.h"
11
12
 
12
13
  typedef struct push_spec {
13
- char *lref;
14
- char *rref;
14
+ struct git_refspec refspec;
15
15
 
16
16
  git_oid loid;
17
17
  git_oid roid;
18
-
19
- bool force;
20
18
  } push_spec;
21
19
 
22
20
  typedef struct push_status {
@@ -0,0 +1,1125 @@
1
+ /*
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
+ *
4
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
5
+ * a Linking Exception. For full terms see the included COPYING file.
6
+ */
7
+
8
+ #include "common.h"
9
+ #include "buffer.h"
10
+ #include "repository.h"
11
+ #include "posix.h"
12
+ #include "filebuf.h"
13
+ #include "merge.h"
14
+ #include "array.h"
15
+ #include "config.h"
16
+ #include "annotated_commit.h"
17
+
18
+ #include <git2/types.h>
19
+ #include <git2/annotated_commit.h>
20
+ #include <git2/rebase.h>
21
+ #include <git2/commit.h>
22
+ #include <git2/reset.h>
23
+ #include <git2/revwalk.h>
24
+ #include <git2/notes.h>
25
+
26
+ #define REBASE_APPLY_DIR "rebase-apply"
27
+ #define REBASE_MERGE_DIR "rebase-merge"
28
+
29
+ #define HEAD_NAME_FILE "head-name"
30
+ #define ORIG_HEAD_FILE "orig-head"
31
+ #define HEAD_FILE "head"
32
+ #define ONTO_FILE "onto"
33
+ #define ONTO_NAME_FILE "onto_name"
34
+ #define QUIET_FILE "quiet"
35
+
36
+ #define MSGNUM_FILE "msgnum"
37
+ #define END_FILE "end"
38
+ #define CMT_FILE_FMT "cmt.%" PRIuZ
39
+ #define CURRENT_FILE "current"
40
+ #define REWRITTEN_FILE "rewritten"
41
+
42
+ #define ORIG_DETACHED_HEAD "detached HEAD"
43
+
44
+ #define NOTES_DEFAULT_REF NULL
45
+
46
+ #define REBASE_DIR_MODE 0777
47
+ #define REBASE_FILE_MODE 0666
48
+
49
+ typedef enum {
50
+ GIT_REBASE_TYPE_NONE = 0,
51
+ GIT_REBASE_TYPE_APPLY = 1,
52
+ GIT_REBASE_TYPE_MERGE = 2,
53
+ GIT_REBASE_TYPE_INTERACTIVE = 3,
54
+ } git_rebase_type_t;
55
+
56
+ struct git_rebase {
57
+ git_repository *repo;
58
+
59
+ git_rebase_type_t type;
60
+ char *state_path;
61
+
62
+ int head_detached : 1,
63
+ quiet : 1,
64
+ started : 1;
65
+
66
+ char *orig_head_name;
67
+ git_oid orig_head_id;
68
+
69
+ git_oid onto_id;
70
+ char *onto_name;
71
+
72
+ git_array_t(git_rebase_operation) operations;
73
+ size_t current;
74
+ };
75
+
76
+ #define GIT_REBASE_STATE_INIT {0}
77
+
78
+ static int rebase_state_type(
79
+ git_rebase_type_t *type_out,
80
+ char **path_out,
81
+ git_repository *repo)
82
+ {
83
+ git_buf path = GIT_BUF_INIT;
84
+ git_rebase_type_t type = GIT_REBASE_TYPE_NONE;
85
+
86
+ if (git_buf_joinpath(&path, repo->path_repository, REBASE_APPLY_DIR) < 0)
87
+ return -1;
88
+
89
+ if (git_path_isdir(git_buf_cstr(&path))) {
90
+ type = GIT_REBASE_TYPE_APPLY;
91
+ goto done;
92
+ }
93
+
94
+ git_buf_clear(&path);
95
+ if (git_buf_joinpath(&path, repo->path_repository, REBASE_MERGE_DIR) < 0)
96
+ return -1;
97
+
98
+ if (git_path_isdir(git_buf_cstr(&path))) {
99
+ type = GIT_REBASE_TYPE_MERGE;
100
+ goto done;
101
+ }
102
+
103
+ done:
104
+ *type_out = type;
105
+
106
+ if (type != GIT_REBASE_TYPE_NONE && path_out)
107
+ *path_out = git_buf_detach(&path);
108
+
109
+ git_buf_free(&path);
110
+
111
+ return 0;
112
+ }
113
+
114
+ GIT_INLINE(int) rebase_readfile(
115
+ git_buf *out,
116
+ git_buf *state_path,
117
+ const char *filename)
118
+ {
119
+ size_t state_path_len = state_path->size;
120
+ int error;
121
+
122
+ git_buf_clear(out);
123
+
124
+ if ((error = git_buf_joinpath(state_path, state_path->ptr, filename)) < 0 ||
125
+ (error = git_futils_readbuffer(out, state_path->ptr)) < 0)
126
+ goto done;
127
+
128
+ git_buf_rtrim(out);
129
+
130
+ done:
131
+ git_buf_truncate(state_path, state_path_len);
132
+ return error;
133
+ }
134
+
135
+ GIT_INLINE(int) rebase_readint(
136
+ size_t *out, git_buf *asc_out, git_buf *state_path, const char *filename)
137
+ {
138
+ int32_t num;
139
+ const char *eol;
140
+ int error = 0;
141
+
142
+ if ((error = rebase_readfile(asc_out, state_path, filename)) < 0)
143
+ return error;
144
+
145
+ if (git__strtol32(&num, asc_out->ptr, &eol, 10) < 0 || num < 0 || *eol) {
146
+ giterr_set(GITERR_REBASE, "The file '%s' contains an invalid numeric value", filename);
147
+ return -1;
148
+ }
149
+
150
+ *out = (size_t) num;
151
+
152
+ return 0;
153
+ }
154
+
155
+ GIT_INLINE(int) rebase_readoid(
156
+ git_oid *out, git_buf *str_out, git_buf *state_path, const char *filename)
157
+ {
158
+ int error;
159
+
160
+ if ((error = rebase_readfile(str_out, state_path, filename)) < 0)
161
+ return error;
162
+
163
+ if (str_out->size != GIT_OID_HEXSZ || git_oid_fromstr(out, str_out->ptr) < 0) {
164
+ giterr_set(GITERR_REBASE, "The file '%s' contains an invalid object ID", filename);
165
+ return -1;
166
+ }
167
+
168
+ return 0;
169
+ }
170
+
171
+ static int rebase_open_merge(git_rebase *rebase)
172
+ {
173
+ git_buf state_path = GIT_BUF_INIT, buf = GIT_BUF_INIT, cmt = GIT_BUF_INIT;
174
+ git_oid current_id = {{0}};
175
+ git_rebase_operation *operation;
176
+ size_t i, msgnum = 0, end;
177
+ int error;
178
+
179
+ if ((error = git_buf_puts(&state_path, rebase->state_path)) < 0)
180
+ goto done;
181
+
182
+ /* Read 'msgnum' if it exists (otherwise, let msgnum = 0) */
183
+ if ((error = rebase_readint(&msgnum, &buf, &state_path, MSGNUM_FILE)) < 0 &&
184
+ error != GIT_ENOTFOUND)
185
+ goto done;
186
+
187
+ if (msgnum) {
188
+ rebase->started = 1;
189
+ rebase->current = msgnum - 1;
190
+ }
191
+
192
+ /* Read 'end' */
193
+ if ((error = rebase_readint(&end, &buf, &state_path, END_FILE)) < 0)
194
+ goto done;
195
+
196
+ /* Read 'current' if it exists */
197
+ if ((error = rebase_readoid(&current_id, &buf, &state_path, CURRENT_FILE)) < 0 &&
198
+ error != GIT_ENOTFOUND)
199
+ goto done;
200
+
201
+ /* Read cmt.* */
202
+ git_array_init_to_size(rebase->operations, end);
203
+ GITERR_CHECK_ARRAY(rebase->operations);
204
+
205
+ for (i = 0; i < end; i++) {
206
+ operation = git_array_alloc(rebase->operations);
207
+ GITERR_CHECK_ALLOC(operation);
208
+
209
+ git_buf_clear(&cmt);
210
+
211
+ if ((error = git_buf_printf(&cmt, "cmt.%" PRIuZ, (i+1))) < 0 ||
212
+ (error = rebase_readoid((git_oid *)&operation->id, &buf, &state_path, cmt.ptr)) < 0)
213
+ goto done;
214
+ }
215
+
216
+ /* Read 'onto_name' */
217
+ if ((error = rebase_readfile(&buf, &state_path, ONTO_NAME_FILE)) < 0)
218
+ goto done;
219
+
220
+ rebase->onto_name = git_buf_detach(&buf);
221
+
222
+ done:
223
+ git_buf_free(&cmt);
224
+ git_buf_free(&state_path);
225
+ git_buf_free(&buf);
226
+
227
+ return error;
228
+ }
229
+
230
+ int git_rebase_open(git_rebase **out, git_repository *repo)
231
+ {
232
+ git_rebase *rebase;
233
+ git_buf path = GIT_BUF_INIT, orig_head_name = GIT_BUF_INIT,
234
+ orig_head_id = GIT_BUF_INIT, onto_id = GIT_BUF_INIT;
235
+ int state_path_len, error;
236
+
237
+ assert(repo);
238
+
239
+ rebase = git__calloc(1, sizeof(git_rebase));
240
+ GITERR_CHECK_ALLOC(rebase);
241
+
242
+ rebase->repo = repo;
243
+
244
+ if ((error = rebase_state_type(&rebase->type, &rebase->state_path, repo)) < 0)
245
+ goto done;
246
+
247
+ if (rebase->type == GIT_REBASE_TYPE_NONE) {
248
+ giterr_set(GITERR_REBASE, "There is no rebase in progress");
249
+ return GIT_ENOTFOUND;
250
+ }
251
+
252
+ if ((error = git_buf_puts(&path, rebase->state_path)) < 0)
253
+ goto done;
254
+
255
+ state_path_len = git_buf_len(&path);
256
+
257
+ if ((error = git_buf_joinpath(&path, path.ptr, HEAD_NAME_FILE)) < 0 ||
258
+ (error = git_futils_readbuffer(&orig_head_name, path.ptr)) < 0)
259
+ goto done;
260
+
261
+ git_buf_rtrim(&orig_head_name);
262
+
263
+ if (strcmp(ORIG_DETACHED_HEAD, orig_head_name.ptr) == 0)
264
+ rebase->head_detached = 1;
265
+
266
+ git_buf_truncate(&path, state_path_len);
267
+
268
+ if ((error = git_buf_joinpath(&path, path.ptr, ORIG_HEAD_FILE)) < 0)
269
+ goto done;
270
+
271
+ if (!git_path_isfile(path.ptr)) {
272
+ /* Previous versions of git.git used 'head' here; support that. */
273
+ git_buf_truncate(&path, state_path_len);
274
+
275
+ if ((error = git_buf_joinpath(&path, path.ptr, HEAD_FILE)) < 0)
276
+ goto done;
277
+ }
278
+
279
+ if ((error = git_futils_readbuffer(&orig_head_id, path.ptr)) < 0)
280
+ goto done;
281
+
282
+ git_buf_rtrim(&orig_head_id);
283
+
284
+ if ((error = git_oid_fromstr(&rebase->orig_head_id, orig_head_id.ptr)) < 0)
285
+ goto done;
286
+
287
+ git_buf_truncate(&path, state_path_len);
288
+
289
+ if ((error = git_buf_joinpath(&path, path.ptr, ONTO_FILE)) < 0 ||
290
+ (error = git_futils_readbuffer(&onto_id, path.ptr)) < 0)
291
+ goto done;
292
+
293
+ git_buf_rtrim(&onto_id);
294
+
295
+ if ((error = git_oid_fromstr(&rebase->onto_id, onto_id.ptr)) < 0)
296
+ goto done;
297
+
298
+ if (!rebase->head_detached)
299
+ rebase->orig_head_name = git_buf_detach(&orig_head_name);
300
+
301
+ switch (rebase->type) {
302
+ case GIT_REBASE_TYPE_INTERACTIVE:
303
+ giterr_set(GITERR_REBASE, "Interactive rebase is not supported");
304
+ error = -1;
305
+ break;
306
+ case GIT_REBASE_TYPE_MERGE:
307
+ error = rebase_open_merge(rebase);
308
+ break;
309
+ case GIT_REBASE_TYPE_APPLY:
310
+ giterr_set(GITERR_REBASE, "Patch application rebase is not supported");
311
+ error = -1;
312
+ break;
313
+ default:
314
+ abort();
315
+ }
316
+
317
+ done:
318
+ if (error == 0)
319
+ *out = rebase;
320
+ else
321
+ git_rebase_free(rebase);
322
+
323
+ git_buf_free(&path);
324
+ git_buf_free(&orig_head_name);
325
+ git_buf_free(&orig_head_id);
326
+ git_buf_free(&onto_id);
327
+ return error;
328
+ }
329
+
330
+ static int rebase_cleanup(git_rebase *rebase)
331
+ {
332
+ return git_path_isdir(rebase->state_path) ?
333
+ git_futils_rmdir_r(rebase->state_path, NULL, GIT_RMDIR_REMOVE_FILES) :
334
+ 0;
335
+ }
336
+
337
+ static int rebase_setupfile(git_rebase *rebase, const char *filename, int flags, const char *fmt, ...)
338
+ {
339
+ git_buf path = GIT_BUF_INIT,
340
+ contents = GIT_BUF_INIT;
341
+ va_list ap;
342
+ int error;
343
+
344
+ va_start(ap, fmt);
345
+ git_buf_vprintf(&contents, fmt, ap);
346
+ va_end(ap);
347
+
348
+ if ((error = git_buf_joinpath(&path, rebase->state_path, filename)) == 0)
349
+ error = git_futils_writebuffer(&contents, path.ptr, flags, REBASE_FILE_MODE);
350
+
351
+ git_buf_free(&path);
352
+ git_buf_free(&contents);
353
+
354
+ return error;
355
+ }
356
+
357
+ static const char *rebase_onto_name(const git_annotated_commit *onto)
358
+ {
359
+ if (onto->ref_name && git__strncmp(onto->ref_name, "refs/heads/", 11) == 0)
360
+ return onto->ref_name + 11;
361
+ else if (onto->ref_name)
362
+ return onto->ref_name;
363
+ else
364
+ return onto->id_str;
365
+ }
366
+
367
+ static int rebase_setupfiles_merge(git_rebase *rebase)
368
+ {
369
+ git_buf commit_filename = GIT_BUF_INIT;
370
+ char id_str[GIT_OID_HEXSZ];
371
+ git_rebase_operation *operation;
372
+ size_t i;
373
+ int error = 0;
374
+
375
+ if ((error = rebase_setupfile(rebase, END_FILE, -1, "%d\n", git_array_size(rebase->operations))) < 0 ||
376
+ (error = rebase_setupfile(rebase, ONTO_NAME_FILE, -1, "%s\n", rebase->onto_name)) < 0)
377
+ goto done;
378
+
379
+ for (i = 0; i < git_array_size(rebase->operations); i++) {
380
+ operation = git_array_get(rebase->operations, i);
381
+
382
+ git_buf_clear(&commit_filename);
383
+ git_buf_printf(&commit_filename, CMT_FILE_FMT, i+1);
384
+
385
+ git_oid_fmt(id_str, &operation->id);
386
+
387
+ if ((error = rebase_setupfile(rebase, commit_filename.ptr, -1,
388
+ "%.*s\n", GIT_OID_HEXSZ, id_str)) < 0)
389
+ goto done;
390
+ }
391
+
392
+ done:
393
+ git_buf_free(&commit_filename);
394
+ return error;
395
+ }
396
+
397
+ static int rebase_setupfiles(git_rebase *rebase)
398
+ {
399
+ char onto[GIT_OID_HEXSZ], orig_head[GIT_OID_HEXSZ];
400
+
401
+ git_oid_fmt(onto, &rebase->onto_id);
402
+ git_oid_fmt(orig_head, &rebase->orig_head_id);
403
+
404
+ if (p_mkdir(rebase->state_path, REBASE_DIR_MODE) < 0) {
405
+ giterr_set(GITERR_OS, "Failed to create rebase directory '%s'", rebase->state_path);
406
+ return -1;
407
+ }
408
+
409
+ if (git_repository__set_orig_head(rebase->repo, &rebase->orig_head_id) < 0 ||
410
+ rebase_setupfile(rebase, HEAD_NAME_FILE, -1, "%s\n", rebase->orig_head_name) < 0 ||
411
+ rebase_setupfile(rebase, ONTO_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, onto) < 0 ||
412
+ rebase_setupfile(rebase, ORIG_HEAD_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, orig_head) < 0 ||
413
+ rebase_setupfile(rebase, QUIET_FILE, -1, rebase->quiet ? "t\n" : "\n") < 0)
414
+ return -1;
415
+
416
+ return rebase_setupfiles_merge(rebase);
417
+ }
418
+
419
+ int git_rebase_init_options(git_rebase_options *opts, unsigned int version)
420
+ {
421
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(
422
+ opts, version, git_rebase_options, GIT_REBASE_OPTIONS_INIT);
423
+ return 0;
424
+ }
425
+
426
+ static int rebase_normalize_opts(
427
+ git_repository *repo,
428
+ git_rebase_options *opts,
429
+ const git_rebase_options *given_opts)
430
+ {
431
+ git_rebase_options default_opts = GIT_REBASE_OPTIONS_INIT;
432
+ git_config *config;
433
+
434
+ if (given_opts)
435
+ memcpy(opts, given_opts, sizeof(git_rebase_options));
436
+ else
437
+ memcpy(opts, &default_opts, sizeof(git_rebase_options));
438
+
439
+ if (git_repository_config(&config, repo) < 0)
440
+ return -1;
441
+
442
+ if (given_opts && given_opts->rewrite_notes_ref) {
443
+ opts->rewrite_notes_ref = git__strdup(given_opts->rewrite_notes_ref);
444
+ GITERR_CHECK_ALLOC(opts->rewrite_notes_ref);
445
+ } else if (git_config__get_bool_force(config, "notes.rewrite.rebase", 1)) {
446
+ const char *rewrite_ref = git_config__get_string_force(
447
+ config, "notes.rewriteref", NOTES_DEFAULT_REF);
448
+
449
+ if (rewrite_ref) {
450
+ opts->rewrite_notes_ref = git__strdup(rewrite_ref);
451
+ GITERR_CHECK_ALLOC(opts->rewrite_notes_ref);
452
+ }
453
+ }
454
+
455
+ git_config_free(config);
456
+
457
+ return 0;
458
+ }
459
+
460
+ static void rebase_opts_free(git_rebase_options *opts)
461
+ {
462
+ if (!opts)
463
+ return;
464
+
465
+ git__free((char *)opts->rewrite_notes_ref);
466
+ }
467
+
468
+ static int rebase_ensure_not_in_progress(git_repository *repo)
469
+ {
470
+ int error;
471
+ git_rebase_type_t type;
472
+
473
+ if ((error = rebase_state_type(&type, NULL, repo)) < 0)
474
+ return error;
475
+
476
+ if (type != GIT_REBASE_TYPE_NONE) {
477
+ giterr_set(GITERR_REBASE, "There is an existing rebase in progress");
478
+ return -1;
479
+ }
480
+
481
+ return 0;
482
+ }
483
+
484
+ static int rebase_ensure_not_dirty(git_repository *repo)
485
+ {
486
+ git_tree *head = NULL;
487
+ git_index *index = NULL;
488
+ git_diff *diff = NULL;
489
+ int error;
490
+
491
+ if ((error = git_repository_head_tree(&head, repo)) < 0 ||
492
+ (error = git_repository_index(&index, repo)) < 0 ||
493
+ (error = git_diff_tree_to_index(&diff, repo, head, index, NULL)) < 0)
494
+ goto done;
495
+
496
+ if (git_diff_num_deltas(diff) > 0) {
497
+ giterr_set(GITERR_REBASE, "Uncommitted changes exist in index");
498
+ error = -1;
499
+ goto done;
500
+ }
501
+
502
+ git_diff_free(diff);
503
+ diff = NULL;
504
+
505
+ if ((error = git_diff_index_to_workdir(&diff, repo, index, NULL)) < 0)
506
+ goto done;
507
+
508
+ if (git_diff_num_deltas(diff) > 0) {
509
+ giterr_set(GITERR_REBASE, "Unstaged changes exist in workdir");
510
+ error = -1;
511
+ }
512
+
513
+ done:
514
+ git_diff_free(diff);
515
+ git_index_free(index);
516
+ git_tree_free(head);
517
+
518
+ return error;
519
+ }
520
+
521
+ static int rebase_init_operations(
522
+ git_rebase *rebase,
523
+ git_repository *repo,
524
+ const git_annotated_commit *branch,
525
+ const git_annotated_commit *upstream,
526
+ const git_annotated_commit *onto)
527
+ {
528
+ git_revwalk *revwalk = NULL;
529
+ git_commit *commit;
530
+ git_oid id;
531
+ bool merge;
532
+ git_rebase_operation *operation;
533
+ int error;
534
+
535
+ if (!upstream)
536
+ upstream = onto;
537
+
538
+ if ((error = git_revwalk_new(&revwalk, rebase->repo)) < 0 ||
539
+ (error = git_revwalk_push(revwalk, git_annotated_commit_id(branch))) < 0 ||
540
+ (error = git_revwalk_hide(revwalk, git_annotated_commit_id(upstream))) < 0)
541
+ goto done;
542
+
543
+ git_revwalk_sorting(revwalk, GIT_SORT_REVERSE | GIT_SORT_TIME);
544
+
545
+ while ((error = git_revwalk_next(&id, revwalk)) == 0) {
546
+ if ((error = git_commit_lookup(&commit, repo, &id)) < 0)
547
+ goto done;
548
+
549
+ merge = (git_commit_parentcount(commit) > 1);
550
+ git_commit_free(commit);
551
+
552
+ if (merge)
553
+ continue;
554
+
555
+ operation = git_array_alloc(rebase->operations);
556
+ operation->type = GIT_REBASE_OPERATION_PICK;
557
+ git_oid_cpy((git_oid *)&operation->id, &id);
558
+ }
559
+
560
+ error = 0;
561
+
562
+ done:
563
+ git_revwalk_free(revwalk);
564
+ return error;
565
+ }
566
+
567
+ static int rebase_init_merge(
568
+ git_rebase *rebase,
569
+ git_repository *repo,
570
+ const git_annotated_commit *branch,
571
+ const git_annotated_commit *upstream,
572
+ const git_annotated_commit *onto)
573
+ {
574
+ if (rebase_init_operations(rebase, repo, branch, upstream, onto) < 0)
575
+ return -1;
576
+
577
+ rebase->onto_name = git__strdup(rebase_onto_name(onto));
578
+ GITERR_CHECK_ALLOC(rebase->onto_name);
579
+
580
+ return 0;
581
+ }
582
+
583
+ static int rebase_init(
584
+ git_rebase *rebase,
585
+ git_repository *repo,
586
+ const git_annotated_commit *branch,
587
+ const git_annotated_commit *upstream,
588
+ const git_annotated_commit *onto,
589
+ const git_rebase_options *opts)
590
+ {
591
+ git_buf state_path = GIT_BUF_INIT;
592
+ int error;
593
+
594
+ git_buf_joinpath(&state_path, repo->path_repository, REBASE_MERGE_DIR);
595
+
596
+ rebase->repo = repo;
597
+ rebase->type = GIT_REBASE_TYPE_MERGE;
598
+ rebase->state_path = git_buf_detach(&state_path);
599
+ rebase->orig_head_name = git__strdup(branch->ref_name ? branch->ref_name : ORIG_DETACHED_HEAD);
600
+ rebase->quiet = opts->quiet;
601
+
602
+ git_oid_cpy(&rebase->orig_head_id, git_annotated_commit_id(branch));
603
+ git_oid_cpy(&rebase->onto_id, git_annotated_commit_id(onto));
604
+
605
+ if (!rebase->orig_head_name || !rebase->state_path)
606
+ return -1;
607
+
608
+ error = rebase_init_merge(rebase, repo, branch, upstream, onto);
609
+
610
+ git_buf_free(&state_path);
611
+
612
+ return error;
613
+ }
614
+
615
+ int git_rebase_init(
616
+ git_rebase **out,
617
+ git_repository *repo,
618
+ const git_annotated_commit *branch,
619
+ const git_annotated_commit *upstream,
620
+ const git_annotated_commit *onto,
621
+ const git_signature *signature,
622
+ const git_rebase_options *given_opts)
623
+ {
624
+ git_rebase *rebase = NULL;
625
+ git_rebase_options opts;
626
+ git_reference *head_ref = NULL;
627
+ git_buf reflog = GIT_BUF_INIT;
628
+ git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
629
+ int error;
630
+
631
+ assert(repo && branch && (upstream || onto));
632
+
633
+ *out = NULL;
634
+
635
+ GITERR_CHECK_VERSION(given_opts, GIT_MERGE_OPTIONS_VERSION, "git_merge_options");
636
+
637
+ if (!onto)
638
+ onto = upstream;
639
+
640
+ checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
641
+
642
+ if ((error = rebase_normalize_opts(repo, &opts, given_opts)) < 0 ||
643
+ (error = git_repository__ensure_not_bare(repo, "rebase")) < 0 ||
644
+ (error = rebase_ensure_not_in_progress(repo)) < 0 ||
645
+ (error = rebase_ensure_not_dirty(repo)) < 0)
646
+ return error;
647
+
648
+ rebase = git__calloc(1, sizeof(git_rebase));
649
+ GITERR_CHECK_ALLOC(rebase);
650
+
651
+ if ((error = rebase_init(rebase, repo, branch, upstream, onto, &opts)) < 0 ||
652
+ (error = rebase_setupfiles(rebase)) < 0 ||
653
+ (error = git_buf_printf(&reflog,
654
+ "rebase: checkout %s", rebase_onto_name(onto))) < 0 ||
655
+ (error = git_reference_create(&head_ref, repo, GIT_HEAD_FILE,
656
+ git_annotated_commit_id(onto), 1, signature, reflog.ptr)) < 0 ||
657
+ (error = git_checkout_head(repo, &checkout_opts)) < 0)
658
+ goto done;
659
+
660
+ *out = rebase;
661
+
662
+ done:
663
+ if (error < 0) {
664
+ rebase_cleanup(rebase);
665
+ git_rebase_free(rebase);
666
+ }
667
+
668
+ git_reference_free(head_ref);
669
+ git_buf_free(&reflog);
670
+ rebase_opts_free(&opts);
671
+
672
+ return error;
673
+ }
674
+
675
+ static void normalize_checkout_opts(
676
+ git_rebase *rebase,
677
+ git_commit *current_commit,
678
+ git_checkout_options *checkout_opts,
679
+ const git_checkout_options *given_checkout_opts)
680
+ {
681
+ if (given_checkout_opts != NULL)
682
+ memcpy(checkout_opts, given_checkout_opts, sizeof(git_checkout_options));
683
+ else {
684
+ git_checkout_options default_checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
685
+ default_checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
686
+
687
+ memcpy(checkout_opts, &default_checkout_opts, sizeof(git_checkout_options));
688
+ }
689
+
690
+ if (!checkout_opts->ancestor_label)
691
+ checkout_opts->ancestor_label = "ancestor";
692
+
693
+ if (rebase->type == GIT_REBASE_TYPE_MERGE) {
694
+ if (!checkout_opts->our_label)
695
+ checkout_opts->our_label = rebase->onto_name;
696
+
697
+ if (!checkout_opts->their_label)
698
+ checkout_opts->their_label = git_commit_summary(current_commit);
699
+ } else {
700
+ abort();
701
+ }
702
+ }
703
+
704
+ GIT_INLINE(int) rebase_movenext(git_rebase *rebase)
705
+ {
706
+ size_t next = rebase->started ? rebase->current + 1 : 0;
707
+
708
+ if (next == git_array_size(rebase->operations))
709
+ return GIT_ITEROVER;
710
+
711
+ rebase->started = 1;
712
+ rebase->current = next;
713
+
714
+ return 0;
715
+ }
716
+
717
+ static int rebase_next_merge(
718
+ git_rebase_operation **out,
719
+ git_rebase *rebase,
720
+ git_checkout_options *given_checkout_opts)
721
+ {
722
+ git_buf path = GIT_BUF_INIT;
723
+ git_checkout_options checkout_opts = {0};
724
+ git_commit *current_commit = NULL, *parent_commit = NULL;
725
+ git_tree *current_tree = NULL, *head_tree = NULL, *parent_tree = NULL;
726
+ git_index *index = NULL;
727
+ git_rebase_operation *operation;
728
+ char current_idstr[GIT_OID_HEXSZ];
729
+ unsigned int parent_count;
730
+ int error;
731
+
732
+ *out = NULL;
733
+
734
+ if ((error = rebase_movenext(rebase)) < 0)
735
+ goto done;
736
+
737
+ operation = git_array_get(rebase->operations, rebase->current);
738
+
739
+ if ((error = git_commit_lookup(&current_commit, rebase->repo, &operation->id)) < 0 ||
740
+ (error = git_commit_tree(&current_tree, current_commit)) < 0 ||
741
+ (error = git_repository_head_tree(&head_tree, rebase->repo)) < 0)
742
+ goto done;
743
+
744
+ if ((parent_count = git_commit_parentcount(current_commit)) > 1) {
745
+ giterr_set(GITERR_REBASE, "Cannot rebase a merge commit");
746
+ error = -1;
747
+ goto done;
748
+ } else if (parent_count) {
749
+ if ((error = git_commit_parent(&parent_commit, current_commit, 0)) < 0 ||
750
+ (error = git_commit_tree(&parent_tree, parent_commit)) < 0)
751
+ goto done;
752
+ }
753
+
754
+ git_oid_fmt(current_idstr, &operation->id);
755
+
756
+ if ((error = rebase_setupfile(rebase, MSGNUM_FILE, -1, "%d\n", rebase->current+1)) < 0 ||
757
+ (error = rebase_setupfile(rebase, CURRENT_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, current_idstr)) < 0)
758
+ goto done;
759
+
760
+ normalize_checkout_opts(rebase, current_commit, &checkout_opts, given_checkout_opts);
761
+
762
+ if ((error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, NULL)) < 0 ||
763
+ (error = git_merge__check_result(rebase->repo, index)) < 0 ||
764
+ (error = git_checkout_index(rebase->repo, index, &checkout_opts)) < 0)
765
+ goto done;
766
+
767
+ *out = operation;
768
+
769
+ done:
770
+ git_index_free(index);
771
+ git_tree_free(current_tree);
772
+ git_tree_free(head_tree);
773
+ git_tree_free(parent_tree);
774
+ git_commit_free(parent_commit);
775
+ git_commit_free(current_commit);
776
+ git_buf_free(&path);
777
+
778
+ return error;
779
+ }
780
+
781
+ int git_rebase_next(
782
+ git_rebase_operation **out,
783
+ git_rebase *rebase,
784
+ git_checkout_options *checkout_opts)
785
+ {
786
+ int error;
787
+
788
+ assert(out && rebase);
789
+
790
+ switch (rebase->type) {
791
+ case GIT_REBASE_TYPE_MERGE:
792
+ error = rebase_next_merge(out, rebase, checkout_opts);
793
+ break;
794
+ default:
795
+ abort();
796
+ }
797
+
798
+ return error;
799
+ }
800
+
801
+ static int rebase_commit_merge(
802
+ git_oid *commit_id,
803
+ git_rebase *rebase,
804
+ const git_signature *author,
805
+ const git_signature *committer,
806
+ const char *message_encoding,
807
+ const char *message)
808
+ {
809
+ git_index *index = NULL;
810
+ git_reference *head = NULL;
811
+ git_commit *current_commit = NULL, *head_commit = NULL, *commit = NULL;
812
+ git_rebase_operation *operation;
813
+ git_tree *head_tree = NULL, *tree = NULL;
814
+ git_diff *diff = NULL;
815
+ git_oid tree_id;
816
+ git_buf reflog_msg = GIT_BUF_INIT;
817
+ char old_idstr[GIT_OID_HEXSZ], new_idstr[GIT_OID_HEXSZ];
818
+ int error;
819
+
820
+ operation = git_array_get(rebase->operations, rebase->current);
821
+ assert(operation);
822
+
823
+ if ((error = git_repository_index(&index, rebase->repo)) < 0)
824
+ goto done;
825
+
826
+ if (git_index_has_conflicts(index)) {
827
+ giterr_set(GITERR_REBASE, "Conflicts have not been resolved");
828
+ error = GIT_EMERGECONFLICT;
829
+ goto done;
830
+ }
831
+
832
+ if ((error = git_commit_lookup(&current_commit, rebase->repo, &operation->id)) < 0 ||
833
+ (error = git_repository_head(&head, rebase->repo)) < 0 ||
834
+ (error = git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)) < 0 ||
835
+ (error = git_commit_tree(&head_tree, head_commit)) < 0 ||
836
+ (error = git_diff_tree_to_index(&diff, rebase->repo, head_tree, index, NULL)) < 0)
837
+ goto done;
838
+
839
+ if (git_diff_num_deltas(diff) == 0) {
840
+ giterr_set(GITERR_REBASE, "This patch has already been applied");
841
+ error = GIT_EAPPLIED;
842
+ goto done;
843
+ }
844
+
845
+ if ((error = git_index_write_tree(&tree_id, index)) < 0 ||
846
+ (error = git_tree_lookup(&tree, rebase->repo, &tree_id)) < 0)
847
+ goto done;
848
+
849
+ if (!author)
850
+ author = git_commit_author(current_commit);
851
+
852
+ if (!message) {
853
+ message_encoding = git_commit_message_encoding(current_commit);
854
+ message = git_commit_message(current_commit);
855
+ }
856
+
857
+ if ((error = git_commit_create(commit_id, rebase->repo, NULL, author,
858
+ committer, message_encoding, message, tree, 1,
859
+ (const git_commit **)&head_commit)) < 0 ||
860
+ (error = git_commit_lookup(&commit, rebase->repo, commit_id)) < 0 ||
861
+ (error = git_reference__update_for_commit(
862
+ rebase->repo, NULL, "HEAD", commit_id, committer, "rebase")) < 0)
863
+ goto done;
864
+
865
+ git_oid_fmt(old_idstr, git_commit_id(current_commit));
866
+ git_oid_fmt(new_idstr, commit_id);
867
+
868
+ error = rebase_setupfile(rebase, REWRITTEN_FILE, O_CREAT|O_WRONLY|O_APPEND,
869
+ "%.*s %.*s\n", GIT_OID_HEXSZ, old_idstr, GIT_OID_HEXSZ, new_idstr);
870
+
871
+ done:
872
+ git_buf_free(&reflog_msg);
873
+ git_commit_free(commit);
874
+ git_diff_free(diff);
875
+ git_tree_free(tree);
876
+ git_tree_free(head_tree);
877
+ git_commit_free(head_commit);
878
+ git_commit_free(current_commit);
879
+ git_reference_free(head);
880
+ git_index_free(index);
881
+
882
+ return error;
883
+ }
884
+
885
+ int git_rebase_commit(
886
+ git_oid *id,
887
+ git_rebase *rebase,
888
+ const git_signature *author,
889
+ const git_signature *committer,
890
+ const char *message_encoding,
891
+ const char *message)
892
+ {
893
+ int error;
894
+
895
+ assert(rebase && committer);
896
+
897
+ switch (rebase->type) {
898
+ case GIT_REBASE_TYPE_MERGE:
899
+ error = rebase_commit_merge(
900
+ id, rebase, author, committer, message_encoding, message);
901
+ break;
902
+ default:
903
+ abort();
904
+ }
905
+
906
+ return error;
907
+ }
908
+
909
+ int git_rebase_abort(git_rebase *rebase, const git_signature *signature)
910
+ {
911
+ git_reference *orig_head_ref = NULL;
912
+ git_commit *orig_head_commit = NULL;
913
+ int error;
914
+
915
+ assert(rebase && signature);
916
+
917
+ error = rebase->head_detached ?
918
+ git_reference_create(&orig_head_ref, rebase->repo, GIT_HEAD_FILE,
919
+ &rebase->orig_head_id, 1, signature, "rebase: aborting") :
920
+ git_reference_symbolic_create(
921
+ &orig_head_ref, rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1,
922
+ signature, "rebase: aborting");
923
+
924
+ if (error < 0)
925
+ goto done;
926
+
927
+ if ((error = git_commit_lookup(
928
+ &orig_head_commit, rebase->repo, &rebase->orig_head_id)) < 0 ||
929
+ (error = git_reset(rebase->repo, (git_object *)orig_head_commit,
930
+ GIT_RESET_HARD, NULL, signature, NULL)) < 0)
931
+ goto done;
932
+
933
+ error = rebase_cleanup(rebase);
934
+
935
+ done:
936
+ git_commit_free(orig_head_commit);
937
+ git_reference_free(orig_head_ref);
938
+
939
+ return error;
940
+ }
941
+
942
+ static int rebase_copy_note(
943
+ git_rebase *rebase,
944
+ git_oid *from,
945
+ git_oid *to,
946
+ const git_signature *committer,
947
+ const git_rebase_options *opts)
948
+ {
949
+ git_note *note = NULL;
950
+ git_oid note_id;
951
+ git_signature *who = NULL;
952
+ int error;
953
+
954
+ if ((error = git_note_read(&note, rebase->repo, opts->rewrite_notes_ref, from)) < 0) {
955
+ if (error == GIT_ENOTFOUND) {
956
+ giterr_clear();
957
+ error = 0;
958
+ }
959
+
960
+ goto done;
961
+ }
962
+
963
+ if (!committer) {
964
+ if((error = git_signature_default(&who, rebase->repo)) < 0) {
965
+ if (error != GIT_ENOTFOUND ||
966
+ (error = git_signature_now(&who, "unknown", "unknown")) < 0)
967
+ goto done;
968
+
969
+ giterr_clear();
970
+ }
971
+
972
+ committer = who;
973
+ }
974
+
975
+ error = git_note_create(&note_id, rebase->repo, git_note_author(note),
976
+ committer, opts->rewrite_notes_ref, to, git_note_message(note), 0);
977
+
978
+ done:
979
+ git_note_free(note);
980
+ git_signature_free(who);
981
+
982
+ return error;
983
+ }
984
+
985
+ static int rebase_copy_notes(
986
+ git_rebase *rebase,
987
+ const git_signature *committer,
988
+ const git_rebase_options *opts)
989
+ {
990
+ git_buf path = GIT_BUF_INIT, rewritten = GIT_BUF_INIT;
991
+ char *pair_list, *fromstr, *tostr, *end;
992
+ git_oid from, to;
993
+ unsigned int linenum = 1;
994
+ int error = 0;
995
+
996
+ if (!opts->rewrite_notes_ref)
997
+ goto done;
998
+
999
+ if ((error = git_buf_joinpath(&path, rebase->state_path, REWRITTEN_FILE)) < 0 ||
1000
+ (error = git_futils_readbuffer(&rewritten, path.ptr)) < 0)
1001
+ goto done;
1002
+
1003
+ pair_list = rewritten.ptr;
1004
+
1005
+ while (*pair_list) {
1006
+ fromstr = pair_list;
1007
+
1008
+ if ((end = strchr(fromstr, '\n')) == NULL)
1009
+ goto on_error;
1010
+
1011
+ pair_list = end+1;
1012
+ *end = '\0';
1013
+
1014
+ if ((end = strchr(fromstr, ' ')) == NULL)
1015
+ goto on_error;
1016
+
1017
+ tostr = end+1;
1018
+ *end = '\0';
1019
+
1020
+ if (strlen(fromstr) != GIT_OID_HEXSZ ||
1021
+ strlen(tostr) != GIT_OID_HEXSZ ||
1022
+ git_oid_fromstr(&from, fromstr) < 0 ||
1023
+ git_oid_fromstr(&to, tostr) < 0)
1024
+ goto on_error;
1025
+
1026
+ if ((error = rebase_copy_note(rebase, &from, &to, committer, opts)) < 0)
1027
+ goto done;
1028
+
1029
+ linenum++;
1030
+ }
1031
+
1032
+ goto done;
1033
+
1034
+ on_error:
1035
+ giterr_set(GITERR_REBASE, "Invalid rewritten file at line %d", linenum);
1036
+ error = -1;
1037
+
1038
+ done:
1039
+ git_buf_free(&rewritten);
1040
+ git_buf_free(&path);
1041
+
1042
+ return error;
1043
+ }
1044
+
1045
+ int git_rebase_finish(
1046
+ git_rebase *rebase,
1047
+ const git_signature *signature,
1048
+ const git_rebase_options *given_opts)
1049
+ {
1050
+ git_rebase_options opts;
1051
+ git_reference *terminal_ref = NULL, *branch_ref = NULL, *head_ref = NULL;
1052
+ git_commit *terminal_commit = NULL;
1053
+ git_buf branch_msg = GIT_BUF_INIT, head_msg = GIT_BUF_INIT;
1054
+ char onto[GIT_OID_HEXSZ];
1055
+ int error;
1056
+
1057
+ assert(rebase);
1058
+
1059
+ if ((error = rebase_normalize_opts(rebase->repo, &opts, given_opts)) < 0)
1060
+ goto done;
1061
+
1062
+ git_oid_fmt(onto, &rebase->onto_id);
1063
+
1064
+ if ((error = git_buf_printf(&branch_msg, "rebase finished: %s onto %.*s",
1065
+ rebase->orig_head_name, GIT_OID_HEXSZ, onto)) < 0 ||
1066
+ (error = git_buf_printf(&head_msg, "rebase finished: returning to %s",
1067
+ rebase->orig_head_name)) < 0 ||
1068
+ (error = git_repository_head(&terminal_ref, rebase->repo)) < 0 ||
1069
+ (error = git_reference_peel((git_object **)&terminal_commit,
1070
+ terminal_ref, GIT_OBJ_COMMIT)) < 0 ||
1071
+ (error = git_reference_create_matching(&branch_ref,
1072
+ rebase->repo, rebase->orig_head_name, git_commit_id(terminal_commit), 1,
1073
+ &rebase->orig_head_id, signature, branch_msg.ptr)) < 0 ||
1074
+ (error = git_reference_symbolic_create(&head_ref,
1075
+ rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1,
1076
+ signature, head_msg.ptr)) < 0 ||
1077
+ (error = rebase_copy_notes(rebase, signature, &opts)) < 0)
1078
+ goto done;
1079
+
1080
+ error = rebase_cleanup(rebase);
1081
+
1082
+ done:
1083
+ git_buf_free(&head_msg);
1084
+ git_buf_free(&branch_msg);
1085
+ git_commit_free(terminal_commit);
1086
+ git_reference_free(head_ref);
1087
+ git_reference_free(branch_ref);
1088
+ git_reference_free(terminal_ref);
1089
+ rebase_opts_free(&opts);
1090
+
1091
+ return error;
1092
+ }
1093
+
1094
+ size_t git_rebase_operation_entrycount(git_rebase *rebase)
1095
+ {
1096
+ assert(rebase);
1097
+
1098
+ return git_array_size(rebase->operations);
1099
+ }
1100
+
1101
+ size_t git_rebase_operation_current(git_rebase *rebase)
1102
+ {
1103
+ assert(rebase);
1104
+
1105
+ return rebase->current;
1106
+ }
1107
+
1108
+ git_rebase_operation *git_rebase_operation_byindex(git_rebase *rebase, size_t idx)
1109
+ {
1110
+ assert(rebase);
1111
+
1112
+ return git_array_get(rebase->operations, idx);
1113
+ }
1114
+
1115
+ void git_rebase_free(git_rebase *rebase)
1116
+ {
1117
+ if (rebase == NULL)
1118
+ return;
1119
+
1120
+ git__free(rebase->onto_name);
1121
+ git__free(rebase->orig_head_name);
1122
+ git__free(rebase->state_path);
1123
+ git_array_clear(rebase->operations);
1124
+ git__free(rebase);
1125
+ }