rugged 0.22.0b5 → 0.22.1b1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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