rugged 0.22.0b5 → 0.22.1b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +19 -3
  3. data/ext/rugged/extconf.rb +21 -5
  4. data/ext/rugged/rugged.c +1 -0
  5. data/ext/rugged/rugged.h +8 -0
  6. data/ext/rugged/rugged_backend.c +34 -0
  7. data/ext/rugged/rugged_branch_collection.c +1 -0
  8. data/ext/rugged/rugged_remote.c +37 -86
  9. data/ext/rugged/rugged_remote_collection.c +2 -1
  10. data/ext/rugged/rugged_repo.c +149 -24
  11. data/ext/rugged/rugged_revwalk.c +1 -2
  12. data/ext/rugged/rugged_submodule.c +1 -1
  13. data/ext/rugged/rugged_tree.c +69 -5
  14. data/lib/rugged/version.rb +1 -1
  15. data/vendor/libgit2/CMakeLists.txt +2 -1
  16. data/vendor/libgit2/include/git2.h +0 -1
  17. data/vendor/libgit2/include/git2/checkout.h +8 -0
  18. data/vendor/libgit2/include/git2/merge.h +8 -0
  19. data/vendor/libgit2/include/git2/push.h +0 -110
  20. data/vendor/libgit2/include/git2/remote.h +30 -1
  21. data/vendor/libgit2/include/git2/revert.h +1 -1
  22. data/vendor/libgit2/include/git2/submodule.h +80 -1
  23. data/vendor/libgit2/include/git2/sys/index.h +2 -2
  24. data/vendor/libgit2/include/git2/{threads.h → sys/openssl.h} +10 -12
  25. data/vendor/libgit2/include/git2/sys/refs.h +11 -0
  26. data/vendor/libgit2/include/git2/tree.h +1 -1
  27. data/vendor/libgit2/include/git2/version.h +3 -3
  28. data/vendor/libgit2/src/attr_file.c +3 -1
  29. data/vendor/libgit2/src/buffer.c +2 -1
  30. data/vendor/libgit2/src/checkout.c +135 -39
  31. data/vendor/libgit2/src/checkout.h +7 -0
  32. data/vendor/libgit2/src/config_file.c +5 -7
  33. data/vendor/libgit2/src/crlf.c +2 -0
  34. data/vendor/libgit2/src/describe.c +6 -2
  35. data/vendor/libgit2/src/diff.c +1 -0
  36. data/vendor/libgit2/src/fileops.c +87 -19
  37. data/vendor/libgit2/src/fileops.h +18 -0
  38. data/vendor/libgit2/src/global.c +1 -1
  39. data/vendor/libgit2/src/ident.c +2 -0
  40. data/vendor/libgit2/src/index.c +4 -4
  41. data/vendor/libgit2/src/merge.c +3 -1
  42. data/vendor/libgit2/src/notes.c +1 -1
  43. data/vendor/libgit2/src/pack.c +1 -0
  44. data/vendor/libgit2/src/path.c +17 -12
  45. data/vendor/libgit2/src/path.h +17 -3
  46. data/vendor/libgit2/src/push.h +110 -0
  47. data/vendor/libgit2/src/rebase.c +4 -2
  48. data/vendor/libgit2/src/remote.c +237 -16
  49. data/vendor/libgit2/src/remote.h +2 -0
  50. data/vendor/libgit2/src/repository.c +7 -3
  51. data/vendor/libgit2/src/submodule.c +229 -18
  52. data/vendor/libgit2/src/transports/local.c +61 -2
  53. data/vendor/libgit2/src/transports/smart_protocol.c +5 -3
  54. data/vendor/libgit2/src/tree.c +2 -2
  55. data/vendor/libgit2/src/util.h +13 -2
  56. data/vendor/libgit2/src/win32/mingw-compat.h +2 -0
  57. data/vendor/libgit2/src/win32/path_w32.h +2 -0
  58. metadata +4 -4
  59. data/vendor/libgit2/cmake/Modules/FindLIBSSH2.cmake +0 -44
@@ -12,6 +12,13 @@
12
12
 
13
13
  #define GIT_CHECKOUT__NOTIFY_CONFLICT_TREE (1u << 12)
14
14
 
15
+ /** Internal structure; this is exposed in future versions. */
16
+ typedef struct {
17
+ size_t mkdir_calls;
18
+ size_t stat_calls;
19
+ size_t chmod_calls;
20
+ } git_checkout_perfdata;
21
+
15
22
  /**
16
23
  * Update the working directory to match the target iterator. The
17
24
  * expected baseline value can be passed in via the checkout options
@@ -1228,13 +1228,6 @@ static int config_parse(git_strmap *values, diskfile_backend *cfg_file, struct r
1228
1228
  if (result < 0)
1229
1229
  break;
1230
1230
 
1231
- var = git__malloc(sizeof(cvar_t));
1232
- GITERR_CHECK_ALLOC(var);
1233
- memset(var, 0x0, sizeof(cvar_t));
1234
- var->entry = git__malloc(sizeof(git_config_entry));
1235
- GITERR_CHECK_ALLOC(var->entry);
1236
- memset(var->entry, 0x0, sizeof(git_config_entry));
1237
-
1238
1231
  git__strtolower(var_name);
1239
1232
  git_buf_printf(&buf, "%s.%s", current_section, var_name);
1240
1233
  git__free(var_name);
@@ -1244,6 +1237,11 @@ static int config_parse(git_strmap *values, diskfile_backend *cfg_file, struct r
1244
1237
  return -1;
1245
1238
  }
1246
1239
 
1240
+ var = git__calloc(1, sizeof(cvar_t));
1241
+ GITERR_CHECK_ALLOC(var);
1242
+ var->entry = git__calloc(1, sizeof(git_config_entry));
1243
+ GITERR_CHECK_ALLOC(var->entry);
1244
+
1247
1245
  var->entry->name = git_buf_detach(&buf);
1248
1246
  var->entry->value = var_value;
1249
1247
  var->entry->level = level;
@@ -345,6 +345,8 @@ static void crlf_cleanup(
345
345
  git_filter *git_crlf_filter_new(void)
346
346
  {
347
347
  struct crlf_filter *f = git__calloc(1, sizeof(struct crlf_filter));
348
+ if (f == NULL)
349
+ return NULL;
348
350
 
349
351
  f->f.version = GIT_FILTER_VERSION;
350
352
  f->f.attributes = "crlf eol text";
@@ -262,6 +262,7 @@ struct possible_tag {
262
262
  static int possible_tag_dup(struct possible_tag **out, struct possible_tag *in)
263
263
  {
264
264
  struct possible_tag *tag;
265
+ int error;
265
266
 
266
267
  tag = git__malloc(sizeof(struct possible_tag));
267
268
  GITERR_CHECK_ALLOC(tag);
@@ -269,8 +270,11 @@ static int possible_tag_dup(struct possible_tag **out, struct possible_tag *in)
269
270
  memcpy(tag, in, sizeof(struct possible_tag));
270
271
  tag->name = NULL;
271
272
 
272
- if (commit_name_dup(&tag->name, in->name) < 0)
273
- return -1;
273
+ if ((error = commit_name_dup(&tag->name, in->name)) < 0) {
274
+ git__free(tag);
275
+ *out = NULL;
276
+ return error;
277
+ }
274
278
 
275
279
  *out = tag;
276
280
  return 0;
@@ -1555,6 +1555,7 @@ int git_diff_format_email(
1555
1555
  if ((offset = (loc - opts->summary)) == 0) {
1556
1556
  giterr_set(GITERR_INVALID, "summary is empty");
1557
1557
  error = -1;
1558
+ goto on_error;
1558
1559
  }
1559
1560
 
1560
1561
  summary = git__calloc(offset + 1, sizeof(char));
@@ -279,11 +279,54 @@ void git_futils_mmap_free(git_map *out)
279
279
  p_munmap(out);
280
280
  }
281
281
 
282
- int git_futils_mkdir(
282
+ GIT_INLINE(int) validate_existing(
283
+ const char *make_path,
284
+ struct stat *st,
285
+ mode_t mode,
286
+ uint32_t flags,
287
+ struct git_futils_mkdir_perfdata *perfdata)
288
+ {
289
+ if ((S_ISREG(st->st_mode) && (flags & GIT_MKDIR_REMOVE_FILES)) ||
290
+ (S_ISLNK(st->st_mode) && (flags & GIT_MKDIR_REMOVE_SYMLINKS))) {
291
+ if (p_unlink(make_path) < 0) {
292
+ giterr_set(GITERR_OS, "Failed to remove %s '%s'",
293
+ S_ISLNK(st->st_mode) ? "symlink" : "file", make_path);
294
+ return GIT_EEXISTS;
295
+ }
296
+
297
+ perfdata->mkdir_calls++;
298
+
299
+ if (p_mkdir(make_path, mode) < 0) {
300
+ giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path);
301
+ return GIT_EEXISTS;
302
+ }
303
+ }
304
+
305
+ else if (S_ISLNK(st->st_mode)) {
306
+ /* Re-stat the target, make sure it's a directory */
307
+ perfdata->stat_calls++;
308
+
309
+ if (p_stat(make_path, st) < 0) {
310
+ giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path);
311
+ return GIT_EEXISTS;
312
+ }
313
+ }
314
+
315
+ else if (!S_ISDIR(st->st_mode)) {
316
+ giterr_set(GITERR_INVALID,
317
+ "Failed to make directory '%s': directory exists", make_path);
318
+ return GIT_EEXISTS;
319
+ }
320
+
321
+ return 0;
322
+ }
323
+
324
+ int git_futils_mkdir_withperf(
283
325
  const char *path,
284
326
  const char *base,
285
327
  mode_t mode,
286
- uint32_t flags)
328
+ uint32_t flags,
329
+ struct git_futils_mkdir_perfdata *perfdata)
287
330
  {
288
331
  int error = -1;
289
332
  git_buf make_path = GIT_BUF_INIT;
@@ -351,34 +394,45 @@ int git_futils_mkdir(
351
394
  *tail = '\0';
352
395
  st.st_mode = 0;
353
396
 
354
- /* make directory */
355
- if (p_mkdir(make_path.ptr, mode) < 0) {
356
- int tmp_errno = giterr_system_last();
397
+ /* See what's going on with this path component */
398
+ perfdata->stat_calls++;
357
399
 
358
- /* ignore error if not at end or if directory already exists */
359
- if (lastch == '\0' &&
360
- (p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode))) {
361
- giterr_system_set(tmp_errno);
400
+ if (p_lstat(make_path.ptr, &st) < 0) {
401
+ perfdata->mkdir_calls++;
402
+
403
+ if (errno != ENOENT || p_mkdir(make_path.ptr, mode) < 0) {
362
404
  giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr);
405
+ error = GIT_EEXISTS;
363
406
  goto done;
364
407
  }
365
408
 
409
+ giterr_clear();
410
+ } else {
366
411
  /* with exclusive create, existing dir is an error */
367
412
  if ((flags & GIT_MKDIR_EXCL) != 0) {
368
- giterr_set(GITERR_OS, "Directory already exists '%s'", make_path.ptr);
413
+ giterr_set(GITERR_INVALID, "Failed to make directory '%s': directory exists", make_path.ptr);
369
414
  error = GIT_EEXISTS;
370
415
  goto done;
371
416
  }
417
+
418
+ if ((error = validate_existing(
419
+ make_path.ptr, &st, mode, flags, perfdata)) < 0)
420
+ goto done;
372
421
  }
373
422
 
374
423
  /* chmod if requested and necessary */
375
424
  if (((flags & GIT_MKDIR_CHMOD_PATH) != 0 ||
376
425
  (lastch == '\0' && (flags & GIT_MKDIR_CHMOD) != 0)) &&
377
- st.st_mode != mode &&
378
- (error = p_chmod(make_path.ptr, mode)) < 0 &&
379
- lastch == '\0') {
380
- giterr_set(GITERR_OS, "Failed to set permissions on '%s'", make_path.ptr);
381
- goto done;
426
+ st.st_mode != mode) {
427
+
428
+ perfdata->chmod_calls++;
429
+
430
+ if ((error = p_chmod(make_path.ptr, mode)) < 0 &&
431
+ lastch == '\0') {
432
+ giterr_set(GITERR_OS, "Failed to set permissions on '%s'",
433
+ make_path.ptr);
434
+ goto done;
435
+ }
382
436
  }
383
437
  }
384
438
 
@@ -386,10 +440,14 @@ int git_futils_mkdir(
386
440
 
387
441
  /* check that full path really is a directory if requested & needed */
388
442
  if ((flags & GIT_MKDIR_VERIFY_DIR) != 0 &&
389
- lastch != '\0' &&
390
- (p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode))) {
391
- giterr_set(GITERR_OS, "Path is not a directory '%s'", make_path.ptr);
392
- error = GIT_ENOTFOUND;
443
+ lastch != '\0') {
444
+ perfdata->stat_calls++;
445
+
446
+ if (p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode)) {
447
+ giterr_set(GITERR_OS, "Path is not a directory '%s'",
448
+ make_path.ptr);
449
+ error = GIT_ENOTFOUND;
450
+ }
393
451
  }
394
452
 
395
453
  done:
@@ -397,6 +455,16 @@ done:
397
455
  return error;
398
456
  }
399
457
 
458
+ int git_futils_mkdir(
459
+ const char *path,
460
+ const char *base,
461
+ mode_t mode,
462
+ uint32_t flags)
463
+ {
464
+ struct git_futils_mkdir_perfdata perfdata = {0};
465
+ return git_futils_mkdir_withperf(path, base, mode, flags, &perfdata);
466
+ }
467
+
400
468
  int git_futils_mkdir_r(const char *path, const char *base, const mode_t mode)
401
469
  {
402
470
  return git_futils_mkdir(path, base, mode, GIT_MKDIR_PATH);
@@ -70,6 +70,8 @@ extern int git_futils_mkdir_r(const char *path, const char *base, const mode_t m
70
70
  * * GIT_MKDIR_SKIP_LAST says to leave off the last element of the path
71
71
  * * GIT_MKDIR_SKIP_LAST2 says to leave off the last 2 elements of the path
72
72
  * * GIT_MKDIR_VERIFY_DIR says confirm final item is a dir, not just EEXIST
73
+ * * GIT_MKDIR_REMOVE_FILES says to remove files and recreate dirs
74
+ * * GIT_MKDIR_REMOVE_SYMLINKS says to remove symlinks and recreate dirs
73
75
  *
74
76
  * Note that the chmod options will be executed even if the directory already
75
77
  * exists, unless GIT_MKDIR_EXCL is given.
@@ -82,8 +84,17 @@ typedef enum {
82
84
  GIT_MKDIR_SKIP_LAST = 16,
83
85
  GIT_MKDIR_SKIP_LAST2 = 32,
84
86
  GIT_MKDIR_VERIFY_DIR = 64,
87
+ GIT_MKDIR_REMOVE_FILES = 128,
88
+ GIT_MKDIR_REMOVE_SYMLINKS = 256,
85
89
  } git_futils_mkdir_flags;
86
90
 
91
+ struct git_futils_mkdir_perfdata
92
+ {
93
+ size_t stat_calls;
94
+ size_t mkdir_calls;
95
+ size_t chmod_calls;
96
+ };
97
+
87
98
  /**
88
99
  * Create a directory or entire path.
89
100
  *
@@ -95,8 +106,15 @@ typedef enum {
95
106
  * @param base Root for relative path. These directories will never be made.
96
107
  * @param mode The mode to use for created directories.
97
108
  * @param flags Combination of the mkdir flags above.
109
+ * @param perfdata Performance data, use `git_futils_mkdir` if you don't want this data.
98
110
  * @return 0 on success, else error code
99
111
  */
112
+ extern int git_futils_mkdir_withperf(const char *path, const char *base, mode_t mode, uint32_t flags, struct git_futils_mkdir_perfdata *perfdata);
113
+
114
+ /**
115
+ * Create a directory or entire path. Similar to `git_futils_mkdir_withperf`
116
+ * without performance data.
117
+ */
100
118
  extern int git_futils_mkdir(const char *path, const char *base, mode_t mode, uint32_t flags);
101
119
 
102
120
  /**
@@ -8,8 +8,8 @@
8
8
  #include "global.h"
9
9
  #include "hash.h"
10
10
  #include "sysdir.h"
11
- #include "git2/threads.h"
12
11
  #include "git2/global.h"
12
+ #include "git2/sys/openssl.h"
13
13
  #include "thread-utils.h"
14
14
 
15
15
 
@@ -115,6 +115,8 @@ static int ident_apply(
115
115
  git_filter *git_ident_filter_new(void)
116
116
  {
117
117
  git_filter *f = git__calloc(1, sizeof(git_filter));
118
+ if (f == NULL)
119
+ return NULL;
118
120
 
119
121
  f->version = GIT_FILTER_VERSION;
120
122
  f->attributes = "+ident"; /* apply to files with ident attribute set */
@@ -1497,10 +1497,10 @@ void git_index_conflict_iterator_free(git_index_conflict_iterator *iterator)
1497
1497
  git__free(iterator);
1498
1498
  }
1499
1499
 
1500
- unsigned int git_index_name_entrycount(git_index *index)
1500
+ size_t git_index_name_entrycount(git_index *index)
1501
1501
  {
1502
1502
  assert(index);
1503
- return (unsigned int)index->names.length;
1503
+ return index->names.length;
1504
1504
  }
1505
1505
 
1506
1506
  const git_index_name_entry *git_index_name_get_byindex(
@@ -1557,10 +1557,10 @@ void git_index_name_clear(git_index *index)
1557
1557
  git_vector_clear(&index->names);
1558
1558
  }
1559
1559
 
1560
- unsigned int git_index_reuc_entrycount(git_index *index)
1560
+ size_t git_index_reuc_entrycount(git_index *index)
1561
1561
  {
1562
1562
  assert(index);
1563
- return (unsigned int)index->reuc.length;
1563
+ return index->reuc.length;
1564
1564
  }
1565
1565
 
1566
1566
  static int index_reuc_insert(
@@ -1550,8 +1550,10 @@ git_merge_diff_list *git_merge_diff_list__alloc(git_repository *repo)
1550
1550
  if (git_vector_init(&diff_list->staged, 0, NULL) < 0 ||
1551
1551
  git_vector_init(&diff_list->conflicts, 0, NULL) < 0 ||
1552
1552
  git_vector_init(&diff_list->resolved, 0, NULL) < 0 ||
1553
- git_pool_init(&diff_list->pool, 1, 0) < 0)
1553
+ git_pool_init(&diff_list->pool, 1, 0) < 0) {
1554
+ git_merge_diff_list__free(diff_list);
1554
1555
  return NULL;
1556
+ }
1555
1557
 
1556
1558
  return diff_list;
1557
1559
  }
@@ -107,7 +107,7 @@ static int tree_write(
107
107
  const git_tree_entry *entry;
108
108
  git_oid tree_oid;
109
109
 
110
- if ((error = git_treebuilder_create(&tb, repo, source_tree)) < 0)
110
+ if ((error = git_treebuilder_new(&tb, repo, source_tree)) < 0)
111
111
  goto cleanup;
112
112
 
113
113
  if (object_oid) {
@@ -158,6 +158,7 @@ static int cache_add(git_pack_cache *cache, git_rawobj *base, git_off_t offset)
158
158
  if (entry) {
159
159
  if (git_mutex_lock(&cache->lock) < 0) {
160
160
  giterr_set(GITERR_OS, "failed to lock cache");
161
+ git__free(entry);
161
162
  return -1;
162
163
  }
163
164
  /* Add it to the cache if nobody else has */
@@ -263,26 +263,31 @@ int git_path_root(const char *path)
263
263
  int git_path_join_unrooted(
264
264
  git_buf *path_out, const char *path, const char *base, ssize_t *root_at)
265
265
  {
266
- int error, root;
266
+ ssize_t root;
267
267
 
268
268
  assert(path && path_out);
269
269
 
270
- root = git_path_root(path);
270
+ root = (ssize_t)git_path_root(path);
271
271
 
272
272
  if (base != NULL && root < 0) {
273
- error = git_buf_joinpath(path_out, base, path);
273
+ if (git_buf_joinpath(path_out, base, path) < 0)
274
+ return -1;
274
275
 
275
- if (root_at)
276
- *root_at = (ssize_t)strlen(base);
277
- }
278
- else {
279
- error = git_buf_sets(path_out, path);
276
+ root = (ssize_t)strlen(base);
277
+ } else {
278
+ if (git_buf_sets(path_out, path) < 0)
279
+ return -1;
280
280
 
281
- if (root_at)
282
- *root_at = (root < 0) ? 0 : (ssize_t)root;
281
+ if (root < 0)
282
+ root = 0;
283
+ else if (base)
284
+ git_path_equal_or_prefixed(base, path, &root);
283
285
  }
284
286
 
285
- return error;
287
+ if (root_at)
288
+ *root_at = root;
289
+
290
+ return 0;
286
291
  }
287
292
 
288
293
  int git_path_prettify(git_buf *path_out, const char *path, const char *base)
@@ -1254,7 +1259,7 @@ GIT_INLINE(bool) verify_dospath(
1254
1259
  if (len < last || git__strncasecmp(component, dospath, 3) != 0)
1255
1260
  return true;
1256
1261
 
1257
- if (trailing_num && !git__isdigit(component[3]))
1262
+ if (trailing_num && (component[3] < '1' || component[3] > '9'))
1258
1263
  return true;
1259
1264
 
1260
1265
  return (len > last &&
@@ -396,21 +396,35 @@ enum { GIT_PATH_NOTEQUAL = 0, GIT_PATH_EQUAL = 1, GIT_PATH_PREFIX = 2 };
396
396
  */
397
397
  GIT_INLINE(int) git_path_equal_or_prefixed(
398
398
  const char *parent,
399
- const char *child)
399
+ const char *child,
400
+ ssize_t *prefixlen)
400
401
  {
401
402
  const char *p = parent, *c = child;
403
+ int lastslash = 0;
402
404
 
403
405
  while (*p && *c) {
406
+ lastslash = (*p == '/');
407
+
404
408
  if (*p++ != *c++)
405
409
  return GIT_PATH_NOTEQUAL;
406
410
  }
407
411
 
408
412
  if (*p != '\0')
409
413
  return GIT_PATH_NOTEQUAL;
410
- if (*c == '\0')
414
+
415
+ if (*c == '\0') {
416
+ if (prefixlen)
417
+ *prefixlen = p - parent;
418
+
411
419
  return GIT_PATH_EQUAL;
412
- if (*c == '/')
420
+ }
421
+
422
+ if (*c == '/' || lastslash) {
423
+ if (prefixlen)
424
+ *prefixlen = (p - parent) - lastslash;
425
+
413
426
  return GIT_PATH_PREFIX;
427
+ }
414
428
 
415
429
  return GIT_PATH_NOTEQUAL;
416
430
  }
@@ -51,4 +51,114 @@ struct git_push {
51
51
  */
52
52
  void git_push_status_free(push_status *status);
53
53
 
54
+ /**
55
+ * Create a new push object
56
+ *
57
+ * @param out New push object
58
+ * @param remote Remote instance
59
+ *
60
+ * @return 0 or an error code
61
+ */
62
+ int git_push_new(git_push **out, git_remote *remote);
63
+
64
+ /**
65
+ * Set options on a push object
66
+ *
67
+ * @param push The push object
68
+ * @param opts The options to set on the push object
69
+ *
70
+ * @return 0 or an error code
71
+ */
72
+ int git_push_set_options(
73
+ git_push *push,
74
+ const git_push_options *opts);
75
+
76
+ /**
77
+ * Set the callbacks for a push
78
+ *
79
+ * @param push The push object
80
+ * @param pack_progress_cb Function to call with progress information during
81
+ * pack building. Be aware that this is called inline with pack building
82
+ * operations, so performance may be affected.
83
+ * @param pack_progress_cb_payload Payload for the pack progress callback.
84
+ * @param transfer_progress_cb Function to call with progress information during
85
+ * the upload portion of a push. Be aware that this is called inline with
86
+ * pack building operations, so performance may be affected.
87
+ * @param transfer_progress_cb_payload Payload for the network progress callback.
88
+ * @return 0 or an error code
89
+ */
90
+ int git_push_set_callbacks(
91
+ git_push *push,
92
+ git_packbuilder_progress pack_progress_cb,
93
+ void *pack_progress_cb_payload,
94
+ git_push_transfer_progress transfer_progress_cb,
95
+ void *transfer_progress_cb_payload);
96
+
97
+ /**
98
+ * Add a refspec to be pushed
99
+ *
100
+ * @param push The push object
101
+ * @param refspec Refspec string
102
+ *
103
+ * @return 0 or an error code
104
+ */
105
+ int git_push_add_refspec(git_push *push, const char *refspec);
106
+
107
+ /**
108
+ * Update remote tips after a push
109
+ *
110
+ * @param push The push object
111
+ * @param signature The identity to use when updating reflogs
112
+ * @param reflog_message The message to insert into the reflogs. If NULL, the
113
+ * default is "update by push".
114
+ *
115
+ * @return 0 or an error code
116
+ */
117
+ int git_push_update_tips(
118
+ git_push *push,
119
+ const git_signature *signature,
120
+ const char *reflog_message);
121
+
122
+ /**
123
+ * Perform the push
124
+ *
125
+ * This function will return an error in case of a protocol error or
126
+ * the server being unable to unpack the data we sent.
127
+ *
128
+ * The return value does not reflect whether the server accepted or
129
+ * refused any reference updates. Use `git_push_status_foreach()` in
130
+ * order to find out which updates were accepted or rejected.
131
+ *
132
+ * @param push The push object
133
+ *
134
+ * @return 0 or an error code
135
+ */
136
+ int git_push_finish(git_push *push);
137
+
138
+ /**
139
+ * Invoke callback `cb' on each status entry
140
+ *
141
+ * For each of the updated references, we receive a status report in the
142
+ * form of `ok refs/heads/master` or `ng refs/heads/master <msg>`.
143
+ * `msg != NULL` means the reference has not been updated for the given
144
+ * reason.
145
+ *
146
+ * Return a non-zero value from the callback to stop the loop.
147
+ *
148
+ * @param push The push object
149
+ * @param cb The callback to call on each object
150
+ *
151
+ * @return 0 on success, non-zero callback return value, or error code
152
+ */
153
+ int git_push_status_foreach(git_push *push,
154
+ int (*cb)(const char *ref, const char *msg, void *data),
155
+ void *data);
156
+
157
+ /**
158
+ * Free the given push object
159
+ *
160
+ * @param push The push object
161
+ */
162
+ void git_push_free(git_push *push);
163
+
54
164
  #endif