rugged 0.17.0.b6 → 0.17.0.b7

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 (158) hide show
  1. data/README.md +3 -3
  2. data/Rakefile +3 -1
  3. data/ext/rugged/rugged.c +30 -0
  4. data/ext/rugged/rugged.h +9 -0
  5. data/ext/rugged/rugged_branch.c +306 -0
  6. data/ext/rugged/rugged_config.c +16 -13
  7. data/ext/rugged/rugged_index.c +25 -0
  8. data/ext/rugged/rugged_object.c +6 -2
  9. data/ext/rugged/rugged_reference.c +11 -18
  10. data/ext/rugged/rugged_revwalk.c +1 -1
  11. data/lib/rugged.rb +1 -0
  12. data/lib/rugged/branch.rb +28 -0
  13. data/lib/rugged/commit.rb +5 -5
  14. data/lib/rugged/repository.rb +32 -7
  15. data/lib/rugged/tag.rb +5 -1
  16. data/lib/rugged/version.rb +1 -1
  17. data/test/branch_test.rb +227 -0
  18. data/test/config_test.rb +1 -1
  19. data/test/fixtures/testrepo.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 +0 -0
  20. data/test/fixtures/testrepo.git/objects/a3/e05719b428a2d0ed7a55c4ce53dcc5768c6d5e +0 -0
  21. data/test/index_test.rb +31 -0
  22. data/test/index_test.rb~ +218 -0
  23. data/test/lib_test.rb +22 -0
  24. data/test/reference_test.rb +5 -3
  25. data/vendor/libgit2/Makefile.embed +1 -1
  26. data/vendor/libgit2/include/git2.h +1 -0
  27. data/vendor/libgit2/include/git2/branch.h +17 -13
  28. data/vendor/libgit2/include/git2/checkout.h +83 -22
  29. data/vendor/libgit2/include/git2/clone.h +6 -3
  30. data/vendor/libgit2/include/git2/common.h +1 -8
  31. data/vendor/libgit2/include/git2/config.h +185 -26
  32. data/vendor/libgit2/include/git2/diff.h +229 -17
  33. data/vendor/libgit2/include/git2/errors.h +39 -1
  34. data/vendor/libgit2/include/git2/ignore.h +6 -3
  35. data/vendor/libgit2/include/git2/indexer.h +1 -0
  36. data/vendor/libgit2/include/git2/merge.h +1 -1
  37. data/vendor/libgit2/include/git2/object.h +7 -4
  38. data/vendor/libgit2/include/git2/odb.h +4 -2
  39. data/vendor/libgit2/include/git2/odb_backend.h +6 -0
  40. data/vendor/libgit2/include/git2/oid.h +2 -0
  41. data/vendor/libgit2/include/git2/pack.h +89 -0
  42. data/vendor/libgit2/include/git2/refs.h +88 -0
  43. data/vendor/libgit2/include/git2/refspec.h +0 -8
  44. data/vendor/libgit2/include/git2/remote.h +34 -1
  45. data/vendor/libgit2/include/git2/repository.h +238 -6
  46. data/vendor/libgit2/include/git2/reset.h +4 -1
  47. data/vendor/libgit2/include/git2/revwalk.h +1 -1
  48. data/vendor/libgit2/include/git2/status.h +19 -14
  49. data/vendor/libgit2/include/git2/strarray.h +54 -0
  50. data/vendor/libgit2/include/git2/submodule.h +451 -45
  51. data/vendor/libgit2/include/git2/tag.h +16 -0
  52. data/vendor/libgit2/include/git2/tree.h +2 -2
  53. data/vendor/libgit2/include/git2/types.h +4 -0
  54. data/vendor/libgit2/src/amiga/map.c +4 -7
  55. data/vendor/libgit2/src/attr.c +21 -13
  56. data/vendor/libgit2/src/attr.h +3 -1
  57. data/vendor/libgit2/src/attr_file.c +14 -14
  58. data/vendor/libgit2/src/attr_file.h +6 -5
  59. data/vendor/libgit2/src/blob.c +22 -12
  60. data/vendor/libgit2/src/branch.c +62 -66
  61. data/vendor/libgit2/src/buffer.c +63 -14
  62. data/vendor/libgit2/src/buffer.h +4 -0
  63. data/vendor/libgit2/src/cache.c +5 -4
  64. data/vendor/libgit2/src/checkout.c +381 -159
  65. data/vendor/libgit2/src/clone.c +221 -94
  66. data/vendor/libgit2/src/common.h +13 -3
  67. data/vendor/libgit2/src/compress.c +53 -0
  68. data/vendor/libgit2/src/compress.h +16 -0
  69. data/vendor/libgit2/src/config.c +380 -175
  70. data/vendor/libgit2/src/config.h +2 -5
  71. data/vendor/libgit2/src/config_file.c +63 -46
  72. data/vendor/libgit2/src/config_file.h +16 -4
  73. data/vendor/libgit2/src/crlf.c +4 -3
  74. data/vendor/libgit2/src/delta.c +491 -0
  75. data/vendor/libgit2/src/delta.h +112 -0
  76. data/vendor/libgit2/src/diff.c +310 -67
  77. data/vendor/libgit2/src/diff.h +10 -1
  78. data/vendor/libgit2/src/diff_output.c +1030 -337
  79. data/vendor/libgit2/src/diff_output.h +86 -0
  80. data/vendor/libgit2/src/errors.c +10 -1
  81. data/vendor/libgit2/src/fetch.c +108 -24
  82. data/vendor/libgit2/src/filebuf.c +8 -2
  83. data/vendor/libgit2/src/fileops.c +342 -177
  84. data/vendor/libgit2/src/fileops.h +84 -7
  85. data/vendor/libgit2/src/filter.c +0 -35
  86. data/vendor/libgit2/src/filter.h +0 -12
  87. data/vendor/libgit2/src/{compat/fnmatch.c → fnmatch.c} +16 -4
  88. data/vendor/libgit2/src/{compat/fnmatch.h → fnmatch.h} +4 -3
  89. data/vendor/libgit2/src/global.c +4 -0
  90. data/vendor/libgit2/src/ignore.c +122 -23
  91. data/vendor/libgit2/src/ignore.h +1 -0
  92. data/vendor/libgit2/src/index.c +56 -10
  93. data/vendor/libgit2/src/index.h +2 -0
  94. data/vendor/libgit2/src/indexer.c +8 -9
  95. data/vendor/libgit2/src/iterator.c +244 -31
  96. data/vendor/libgit2/src/iterator.h +30 -1
  97. data/vendor/libgit2/src/message.c +1 -1
  98. data/vendor/libgit2/src/netops.c +44 -4
  99. data/vendor/libgit2/src/object.c +80 -69
  100. data/vendor/libgit2/src/object.h +39 -0
  101. data/vendor/libgit2/src/odb.c +79 -15
  102. data/vendor/libgit2/src/odb.h +20 -5
  103. data/vendor/libgit2/src/odb_pack.c +65 -33
  104. data/vendor/libgit2/src/oid.c +0 -3
  105. data/vendor/libgit2/src/pack-objects.c +1315 -0
  106. data/vendor/libgit2/src/pack-objects.h +87 -0
  107. data/vendor/libgit2/src/pack.c +36 -12
  108. data/vendor/libgit2/src/pack.h +1 -0
  109. data/vendor/libgit2/src/path.c +42 -9
  110. data/vendor/libgit2/src/path.h +14 -0
  111. data/vendor/libgit2/src/pkt.c +52 -2
  112. data/vendor/libgit2/src/pkt.h +10 -0
  113. data/vendor/libgit2/src/pool.h +11 -0
  114. data/vendor/libgit2/src/posix.h +8 -0
  115. data/vendor/libgit2/src/protocol.c +24 -2
  116. data/vendor/libgit2/src/protocol.h +4 -0
  117. data/vendor/libgit2/src/reflog.c +1 -1
  118. data/vendor/libgit2/src/refs.c +292 -124
  119. data/vendor/libgit2/src/refs.h +4 -2
  120. data/vendor/libgit2/src/refspec.c +117 -19
  121. data/vendor/libgit2/src/refspec.h +19 -0
  122. data/vendor/libgit2/src/remote.c +152 -48
  123. data/vendor/libgit2/src/remote.h +4 -1
  124. data/vendor/libgit2/src/repo_template.h +58 -0
  125. data/vendor/libgit2/src/repository.c +594 -179
  126. data/vendor/libgit2/src/repository.h +23 -22
  127. data/vendor/libgit2/src/reset.c +71 -29
  128. data/vendor/libgit2/src/revparse.c +26 -17
  129. data/vendor/libgit2/src/revwalk.c +36 -19
  130. data/vendor/libgit2/src/sha1.h +7 -0
  131. data/vendor/libgit2/src/{sha1.c → sha1/sha1.c} +0 -0
  132. data/vendor/libgit2/src/signature.c +12 -10
  133. data/vendor/libgit2/src/status.c +52 -6
  134. data/vendor/libgit2/src/submodule.c +1363 -255
  135. data/vendor/libgit2/src/submodule.h +102 -0
  136. data/vendor/libgit2/src/tag.c +42 -26
  137. data/vendor/libgit2/src/thread-utils.h +7 -7
  138. data/vendor/libgit2/src/transport.h +15 -1
  139. data/vendor/libgit2/src/transports/git.c +1 -1
  140. data/vendor/libgit2/src/transports/http.c +197 -36
  141. data/vendor/libgit2/src/tree.c +3 -3
  142. data/vendor/libgit2/src/unix/map.c +2 -0
  143. data/vendor/libgit2/src/unix/posix.h +1 -8
  144. data/vendor/libgit2/src/util.c +6 -1
  145. data/vendor/libgit2/src/util.h +7 -0
  146. data/vendor/libgit2/src/vector.c +16 -0
  147. data/vendor/libgit2/src/vector.h +1 -0
  148. data/vendor/libgit2/src/win32/dir.c +8 -21
  149. data/vendor/libgit2/src/win32/findfile.c +149 -0
  150. data/vendor/libgit2/src/win32/findfile.h +23 -0
  151. data/vendor/libgit2/src/win32/posix.h +3 -7
  152. data/vendor/libgit2/src/win32/posix_w32.c +44 -102
  153. data/vendor/libgit2/src/win32/pthread.c +68 -0
  154. data/vendor/libgit2/src/win32/pthread.h +7 -0
  155. data/vendor/libgit2/src/win32/utf-conv.c +60 -71
  156. data/vendor/libgit2/src/win32/utf-conv.h +4 -3
  157. metadata +70 -71
  158. data/vendor/libgit2/include/git2/windows.h +0 -59
@@ -11,6 +11,7 @@
11
11
  #include "types.h"
12
12
  #include "oid.h"
13
13
  #include "object.h"
14
+ #include "strarray.h"
14
15
 
15
16
  /**
16
17
  * @file git2/tag.h
@@ -277,6 +278,21 @@ GIT_EXTERN(int) git_tag_list_match(
277
278
  const char *pattern,
278
279
  git_repository *repo);
279
280
 
281
+
282
+ typedef int (*git_tag_foreach_cb)(const char *name, git_oid *oid, void *data);
283
+ /**
284
+ * Call callback `cb' for each tag in the repository
285
+ *
286
+ * @param repo Repository
287
+ * @param cb Callback function
288
+ * @param cb_data Pointer to callback data (optional)
289
+ */
290
+ GIT_EXTERN(int) git_tag_foreach(
291
+ git_repository *repo,
292
+ git_tag_foreach_cb cb,
293
+ void *cb_data);
294
+
295
+
280
296
  /**
281
297
  * Recursively peel a tag until a non tag git_object
282
298
  * is met
@@ -100,7 +100,7 @@ GIT_EXTERN(git_tree_entry *) git_tree_entry_dup(const git_tree_entry *entry);
100
100
  * @param tree a previously loaded tree.
101
101
  * @return object identity for the tree.
102
102
  */
103
- GIT_EXTERN(const git_oid *) git_tree_id(git_tree *tree);
103
+ GIT_EXTERN(const git_oid *) git_tree_id(const git_tree *tree);
104
104
 
105
105
  /**
106
106
  * Get the number of entries listed in a tree
@@ -108,7 +108,7 @@ GIT_EXTERN(const git_oid *) git_tree_id(git_tree *tree);
108
108
  * @param tree a previously loaded tree.
109
109
  * @return the number of entries in the tree
110
110
  */
111
- GIT_EXTERN(unsigned int) git_tree_entrycount(git_tree *tree);
111
+ GIT_EXTERN(unsigned int) git_tree_entrycount(const git_tree *tree);
112
112
 
113
113
  /**
114
114
  * Lookup a tree entry by its filename
@@ -137,6 +137,9 @@ typedef struct git_reflog git_reflog;
137
137
  /** Representation of a git note */
138
138
  typedef struct git_note git_note;
139
139
 
140
+ /** Representation of a git packbuilder */
141
+ typedef struct git_packbuilder git_packbuilder;
142
+
140
143
  /** Time in a signature */
141
144
  typedef struct git_time {
142
145
  git_time_t time; /** time in seconds from epoch */
@@ -173,6 +176,7 @@ typedef enum {
173
176
  typedef enum {
174
177
  GIT_RESET_SOFT = 1,
175
178
  GIT_RESET_MIXED = 2,
179
+ GIT_RESET_HARD = 3,
176
180
  } git_reset_type;
177
181
 
178
182
  /** Valid modes for index and tree entries. */
@@ -24,18 +24,15 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
24
24
  return -1;
25
25
  }
26
26
 
27
- if((out->data = malloc(len))) {
28
- p_lseek(fd, offset, SEEK_SET);
29
- p_read(fd, out->data, len);
30
- }
27
+ out->data = malloc(len);
28
+ GITERR_CHECK_ALLOC(out->data);
31
29
 
32
- if (!out->data || (out->data == MAP_FAILED)) {
33
- giterr_set(GITERR_OS, "Failed to mmap. Could not write data");
30
+ if (p_lseek(fd, offset, SEEK_SET) < 0 || p_read(fd, out->data, len) != len)
31
+ giterr_set(GITERR_OS, "mmap emulation failed");
34
32
  return -1;
35
33
  }
36
34
 
37
35
  out->len = len;
38
-
39
36
  return 0;
40
37
  }
41
38
 
@@ -188,6 +188,7 @@ int git_attr_foreach(
188
188
 
189
189
  error = callback(assign->name, assign->value, payload);
190
190
  if (error) {
191
+ giterr_clear();
191
192
  error = GIT_EUSER;
192
193
  goto cleanup;
193
194
  }
@@ -375,6 +376,7 @@ int git_attr_cache__push_file(
375
376
  const char *filename,
376
377
  git_attr_file_source source,
377
378
  git_attr_file_parser parse,
379
+ void* parsedata,
378
380
  git_vector *stack)
379
381
  {
380
382
  int error = 0;
@@ -435,7 +437,7 @@ int git_attr_cache__push_file(
435
437
  goto finish;
436
438
  }
437
439
 
438
- if (parse && (error = parse(repo, content, file)) < 0)
440
+ if (parse && (error = parse(repo, parsedata, content, file)) < 0)
439
441
  goto finish;
440
442
 
441
443
  git_strmap_insert(cache->files, file->key, file, error); //-V595
@@ -467,7 +469,7 @@ finish:
467
469
  }
468
470
 
469
471
  #define push_attr_file(R,S,B,F) \
470
- git_attr_cache__push_file((R),(B),(F),GIT_ATTR_FILE_FROM_FILE,git_attr_file__parse_buffer,(S))
472
+ git_attr_cache__push_file((R),(B),(F),GIT_ATTR_FILE_FROM_FILE,git_attr_file__parse_buffer,NULL,(S))
471
473
 
472
474
  typedef struct {
473
475
  git_repository *repo;
@@ -516,7 +518,7 @@ static int push_one_attr(void *ref, git_buf *path)
516
518
  for (i = 0; !error && i < n_src; ++i)
517
519
  error = git_attr_cache__push_file(
518
520
  info->repo, path->ptr, GIT_ATTR_FILE, src[i],
519
- git_attr_file__parse_buffer, info->files);
521
+ git_attr_file__parse_buffer, NULL, info->files);
520
522
 
521
523
  return error;
522
524
  }
@@ -590,6 +592,18 @@ static int collect_attr_files(
590
592
  return error;
591
593
  }
592
594
 
595
+ static char *try_global_default(const char *relpath)
596
+ {
597
+ git_buf dflt = GIT_BUF_INIT;
598
+ char *rval = NULL;
599
+
600
+ if (!git_futils_find_global_file(&dflt, relpath))
601
+ rval = git_buf_detach(&dflt);
602
+
603
+ git_buf_free(&dflt);
604
+
605
+ return rval;
606
+ }
593
607
 
594
608
  int git_attr_cache__init(git_repository *repo)
595
609
  {
@@ -607,20 +621,14 @@ int git_attr_cache__init(git_repository *repo)
607
621
  ret = git_config_get_string(&cache->cfg_attr_file, cfg, GIT_ATTR_CONFIG);
608
622
  if (ret < 0 && ret != GIT_ENOTFOUND)
609
623
  return ret;
624
+ if (ret == GIT_ENOTFOUND)
625
+ cache->cfg_attr_file = try_global_default(GIT_ATTR_CONFIG_DEFAULT);
610
626
 
611
627
  ret = git_config_get_string(&cache->cfg_excl_file, cfg, GIT_IGNORE_CONFIG);
612
628
  if (ret < 0 && ret != GIT_ENOTFOUND)
613
629
  return ret;
614
-
615
- if (ret == GIT_ENOTFOUND) {
616
- git_buf dflt = GIT_BUF_INIT;
617
-
618
- ret = git_futils_find_global_file(&dflt, GIT_IGNORE_CONFIG_DEFAULT);
619
- if (!ret)
620
- cache->cfg_excl_file = git_buf_detach(&dflt);
621
-
622
- git_buf_free(&dflt);
623
- }
630
+ if (ret == GIT_ENOTFOUND)
631
+ cache->cfg_excl_file = try_global_default(GIT_IGNORE_CONFIG_DEFAULT);
624
632
 
625
633
  giterr_clear();
626
634
 
@@ -11,6 +11,7 @@
11
11
  #include "strmap.h"
12
12
 
13
13
  #define GIT_ATTR_CONFIG "core.attributesfile"
14
+ #define GIT_ATTR_CONFIG_DEFAULT ".config/git/attributes"
14
15
  #define GIT_IGNORE_CONFIG "core.excludesfile"
15
16
  #define GIT_IGNORE_CONFIG_DEFAULT ".config/git/ignore"
16
17
 
@@ -24,7 +25,7 @@ typedef struct {
24
25
  } git_attr_cache;
25
26
 
26
27
  typedef int (*git_attr_file_parser)(
27
- git_repository *, const char *, git_attr_file *);
28
+ git_repository *, void *, const char *, git_attr_file *);
28
29
 
29
30
  extern int git_attr_cache__init(git_repository *repo);
30
31
 
@@ -40,6 +41,7 @@ extern int git_attr_cache__push_file(
40
41
  const char *filename,
41
42
  git_attr_file_source source,
42
43
  git_attr_file_parser parse,
44
+ void *parsedata, /* passed through to parse function */
43
45
  git_vector *stack);
44
46
 
45
47
  extern int git_attr_cache__internal_file(
@@ -53,13 +53,15 @@ fail:
53
53
  }
54
54
 
55
55
  int git_attr_file__parse_buffer(
56
- git_repository *repo, const char *buffer, git_attr_file *attrs)
56
+ git_repository *repo, void *parsedata, const char *buffer, git_attr_file *attrs)
57
57
  {
58
58
  int error = 0;
59
59
  const char *scan = NULL;
60
60
  char *context = NULL;
61
61
  git_attr_rule *rule = NULL;
62
62
 
63
+ GIT_UNUSED(parsedata);
64
+
63
65
  assert(buffer && attrs);
64
66
 
65
67
  scan = buffer;
@@ -123,7 +125,7 @@ int git_attr_file__new_and_load(
123
125
 
124
126
  if (!(error = git_futils_readbuffer(&content, path)))
125
127
  error = git_attr_file__parse_buffer(
126
- NULL, git_buf_cstr(&content), *attrs_ptr);
128
+ NULL, NULL, git_buf_cstr(&content), *attrs_ptr);
127
129
 
128
130
  git_buf_free(&content);
129
131
 
@@ -207,16 +209,17 @@ bool git_attr_fnmatch__match(
207
209
  const git_attr_path *path)
208
210
  {
209
211
  int fnm;
212
+ int icase_flags = (match->flags & GIT_ATTR_FNMATCH_ICASE) ? FNM_CASEFOLD : 0;
210
213
 
211
214
  if (match->flags & GIT_ATTR_FNMATCH_DIRECTORY && !path->is_dir)
212
215
  return false;
213
216
 
214
217
  if (match->flags & GIT_ATTR_FNMATCH_FULLPATH)
215
- fnm = p_fnmatch(match->pattern, path->path, FNM_PATHNAME);
218
+ fnm = p_fnmatch(match->pattern, path->path, FNM_PATHNAME | icase_flags);
216
219
  else if (path->is_dir)
217
- fnm = p_fnmatch(match->pattern, path->basename, FNM_LEADING_DIR);
220
+ fnm = p_fnmatch(match->pattern, path->basename, FNM_LEADING_DIR | icase_flags);
218
221
  else
219
- fnm = p_fnmatch(match->pattern, path->basename, 0);
222
+ fnm = p_fnmatch(match->pattern, path->basename, icase_flags);
220
223
 
221
224
  return (fnm == FNM_NOMATCH) ? false : true;
222
225
  }
@@ -250,18 +253,15 @@ git_attr_assignment *git_attr_rule__lookup_assignment(
250
253
  int git_attr_path__init(
251
254
  git_attr_path *info, const char *path, const char *base)
252
255
  {
256
+ ssize_t root;
257
+
253
258
  /* build full path as best we can */
254
259
  git_buf_init(&info->full, 0);
255
260
 
256
- if (base != NULL && git_path_root(path) < 0) {
257
- if (git_buf_joinpath(&info->full, base, path) < 0)
258
- return -1;
259
- info->path = info->full.ptr + strlen(base);
260
- } else {
261
- if (git_buf_sets(&info->full, path) < 0)
262
- return -1;
263
- info->path = info->full.ptr;
264
- }
261
+ if (git_path_join_unrooted(&info->full, path, base, &root) < 0)
262
+ return -1;
263
+
264
+ info->path = info->full.ptr + root;
265
265
 
266
266
  /* remove trailing slashes */
267
267
  while (info->full.size > 0) {
@@ -23,6 +23,7 @@
23
23
  #define GIT_ATTR_FNMATCH_IGNORE (1U << 4)
24
24
  #define GIT_ATTR_FNMATCH_HASWILD (1U << 5)
25
25
  #define GIT_ATTR_FNMATCH_ALLOWSPACE (1U << 6)
26
+ #define GIT_ATTR_FNMATCH_ICASE (1U << 7)
26
27
 
27
28
  extern const char *git_attr__true;
28
29
  extern const char *git_attr__false;
@@ -70,10 +71,10 @@ typedef struct {
70
71
  } git_attr_file;
71
72
 
72
73
  typedef struct {
73
- git_buf full;
74
- const char *path;
75
- const char *basename;
76
- int is_dir;
74
+ git_buf full;
75
+ char *path;
76
+ char *basename;
77
+ int is_dir;
77
78
  } git_attr_path;
78
79
 
79
80
  typedef enum {
@@ -96,7 +97,7 @@ extern void git_attr_file__free(git_attr_file *file);
96
97
  extern void git_attr_file__clear_rules(git_attr_file *file);
97
98
 
98
99
  extern int git_attr_file__parse_buffer(
99
- git_repository *repo, const char *buf, git_attr_file *file);
100
+ git_repository *repo, void *parsedata, const char *buf, git_attr_file *file);
100
101
 
101
102
  extern int git_attr_file__lookup_one(
102
103
  git_attr_file *file,
@@ -68,6 +68,7 @@ static int write_file_stream(
68
68
  int fd, error;
69
69
  char buffer[4096];
70
70
  git_odb_stream *stream = NULL;
71
+ ssize_t read_len = -1, written = 0;
71
72
 
72
73
  if ((error = git_odb_open_wstream(
73
74
  &stream, odb, (size_t)file_size, GIT_OBJ_BLOB)) < 0)
@@ -78,20 +79,18 @@ static int write_file_stream(
78
79
  return -1;
79
80
  }
80
81
 
81
- while (!error && file_size > 0) {
82
- ssize_t read_len = p_read(fd, buffer, sizeof(buffer));
83
-
84
- if (read_len < 0) {
85
- giterr_set(
86
- GITERR_OS, "Failed to create blob. Can't read whole file");
87
- error = -1;
88
- }
89
- else if (!(error = stream->write(stream, buffer, read_len)))
90
- file_size -= read_len;
82
+ while (!error && (read_len = p_read(fd, buffer, sizeof(buffer))) > 0) {
83
+ error = stream->write(stream, buffer, read_len);
84
+ written += read_len;
91
85
  }
92
86
 
93
87
  p_close(fd);
94
88
 
89
+ if (written != file_size || read_len < 0) {
90
+ giterr_set(GITERR_OS, "Failed to read file into stream");
91
+ error = -1;
92
+ }
93
+
95
94
  if (!error)
96
95
  error = stream->finalize_write(oid, stream);
97
96
 
@@ -212,8 +211,10 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
212
211
  const char *workdir;
213
212
  int error;
214
213
 
214
+ if ((error = git_repository__ensure_not_bare(repo, "create blob from file")) < 0)
215
+ return error;
216
+
215
217
  workdir = git_repository_workdir(repo);
216
- assert(workdir); /* error to call this on bare repo */
217
218
 
218
219
  if (git_buf_joinpath(&full_path, workdir, path) < 0) {
219
220
  git_buf_free(&full_path);
@@ -254,11 +255,19 @@ int git_blob_create_fromchunks(
254
255
  int error = -1, read_bytes;
255
256
  char *content = NULL;
256
257
  git_filebuf file = GIT_FILEBUF_INIT;
258
+ git_buf path = GIT_BUF_INIT;
259
+
260
+ if (git_buf_join_n(
261
+ &path, '/', 3,
262
+ git_repository_path(repo),
263
+ GIT_OBJECTS_DIR,
264
+ "streamed") < 0)
265
+ goto cleanup;
257
266
 
258
267
  content = git__malloc(BUFFER_SIZE);
259
268
  GITERR_CHECK_ALLOC(content);
260
269
 
261
- if (git_filebuf_open(&file, hintpath == NULL ? "streamed" : hintpath, GIT_FILEBUF_TEMPORARY) < 0)
270
+ if (git_filebuf_open(&file, git_buf_cstr(&path), GIT_FILEBUF_TEMPORARY) < 0)
262
271
  goto cleanup;
263
272
 
264
273
  while (1) {
@@ -282,6 +291,7 @@ int git_blob_create_fromchunks(
282
291
  error = blob_create_internal(oid, repo, file.path_lock, hintpath, hintpath != NULL);
283
292
 
284
293
  cleanup:
294
+ git_buf_free(&path);
285
295
  git_filebuf_cleanup(&file);
286
296
  git__free(content);
287
297
  return error;
@@ -50,6 +50,12 @@ static int create_error_invalid(const char *msg)
50
50
  return -1;
51
51
  }
52
52
 
53
+ static int not_a_local_branch(git_reference *ref)
54
+ {
55
+ giterr_set(GITERR_INVALID, "Reference '%s' is not a local branch.", git_reference_name(ref));
56
+ return -1;
57
+ }
58
+
53
59
  int git_branch_create(
54
60
  git_reference **ref_out,
55
61
  git_repository *repository,
@@ -57,7 +63,6 @@ int git_branch_create(
57
63
  const git_object *target,
58
64
  int force)
59
65
  {
60
- git_otype target_type = GIT_OBJ_BAD;
61
66
  git_object *commit = NULL;
62
67
  git_reference *branch = NULL;
63
68
  git_buf canonical_branch_name = GIT_BUF_INIT;
@@ -66,80 +71,46 @@ int git_branch_create(
66
71
  assert(branch_name && target && ref_out);
67
72
  assert(git_object_owner(target) == repository);
68
73
 
69
- target_type = git_object_type(target);
70
-
71
- switch (target_type)
72
- {
73
- case GIT_OBJ_TAG:
74
- if (git_tag_peel(&commit, (git_tag *)target) < 0)
75
- goto cleanup;
76
-
77
- if (git_object_type(commit) != GIT_OBJ_COMMIT) {
78
- create_error_invalid("The given target does not resolve to a commit");
79
- goto cleanup;
80
- }
81
- break;
82
-
83
- case GIT_OBJ_COMMIT:
84
- commit = (git_object *)target;
85
- break;
86
-
87
- default:
88
- return create_error_invalid("Only git_tag and git_commit objects are valid targets.");
89
- }
74
+ if (git_object_peel(&commit, (git_object *)target, GIT_OBJ_COMMIT) < 0)
75
+ return create_error_invalid("The given target does not resolve to a commit");
90
76
 
91
77
  if (git_buf_joinpath(&canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name) < 0)
92
78
  goto cleanup;
93
79
 
94
- if (git_reference_create_oid(&branch, repository,
95
- git_buf_cstr(&canonical_branch_name), git_object_id(commit), force) < 0)
96
- goto cleanup;
80
+ error = git_reference_create_oid(&branch, repository,
81
+ git_buf_cstr(&canonical_branch_name), git_object_id(commit), force);
97
82
 
98
- *ref_out = branch;
99
- error = 0;
83
+ if (!error)
84
+ *ref_out = branch;
100
85
 
101
86
  cleanup:
102
- if (target_type == GIT_OBJ_TAG)
103
- git_object_free(commit);
104
-
87
+ git_object_free(commit);
105
88
  git_buf_free(&canonical_branch_name);
106
89
  return error;
107
90
  }
108
91
 
109
- int git_branch_delete(git_repository *repo, const char *branch_name, git_branch_t branch_type)
92
+ int git_branch_delete(git_reference *branch)
110
93
  {
111
- git_reference *branch = NULL;
112
- git_reference *head = NULL;
113
- int error;
114
-
115
- assert(repo && branch_name);
116
- assert((branch_type == GIT_BRANCH_LOCAL) || (branch_type == GIT_BRANCH_REMOTE));
94
+ int is_head;
117
95
 
118
- if ((error = retrieve_branch_reference(&branch, repo, branch_name, branch_type == GIT_BRANCH_REMOTE)) < 0)
119
- return error;
96
+ assert(branch);
120
97
 
121
- if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0) {
122
- giterr_set(GITERR_REFERENCE, "Cannot locate HEAD.");
123
- goto on_error;
124
- }
125
-
126
- if ((git_reference_type(head) == GIT_REF_SYMBOLIC)
127
- && (strcmp(git_reference_target(head), git_reference_name(branch)) == 0)) {
128
- giterr_set(GITERR_REFERENCE,
129
- "Cannot delete branch '%s' as it is the current HEAD of the repository.", branch_name);
130
- goto on_error;
98
+ if (!git_reference_is_branch(branch) &&
99
+ !git_reference_is_remote(branch)) {
100
+ giterr_set(GITERR_INVALID, "Reference '%s' is not a valid branch.", git_reference_name(branch));
101
+ return -1;
131
102
  }
132
103
 
133
- if (git_reference_delete(branch) < 0)
134
- goto on_error;
104
+ if ((is_head = git_branch_is_head(branch)) < 0)
105
+ return is_head;
135
106
 
136
- git_reference_free(head);
137
- return 0;
107
+ if (is_head) {
108
+ giterr_set(GITERR_REFERENCE,
109
+ "Cannot delete branch '%s' as it is the current HEAD of the repository.", git_reference_name(branch));
110
+ return -1;
111
+ }
138
112
 
139
- on_error:
140
- git_reference_free(head);
141
- git_reference_free(branch);
142
- return -1;
113
+ return git_reference_delete(branch);
143
114
  }
144
115
 
145
116
  typedef struct {
@@ -185,12 +156,6 @@ int git_branch_foreach(
185
156
  return git_reference_foreach(repo, GIT_REF_LISTALL, &branch_foreach_cb, (void *)&filter);
186
157
  }
187
158
 
188
- static int not_a_local_branch(git_reference *ref)
189
- {
190
- giterr_set(GITERR_INVALID, "Reference '%s' is not a local branch.", git_reference_name(ref));
191
- return -1;
192
- }
193
-
194
159
  int git_branch_move(
195
160
  git_reference *branch,
196
161
  const char *new_branch_name,
@@ -271,9 +236,11 @@ int git_branch_tracking(
271
236
  goto cleanup;
272
237
 
273
238
  refspec = git_remote_fetchspec(remote);
274
- if (refspec == NULL) {
275
- error = GIT_ENOTFOUND;
276
- goto cleanup;
239
+ if (refspec == NULL
240
+ || refspec->src == NULL
241
+ || refspec->dst == NULL) {
242
+ error = GIT_ENOTFOUND;
243
+ goto cleanup;
277
244
  }
278
245
 
279
246
  if (git_refspec_transform_r(&buf, refspec, merge_name) < 0)
@@ -292,3 +259,32 @@ cleanup:
292
259
  git_buf_free(&buf);
293
260
  return error;
294
261
  }
262
+
263
+ int git_branch_is_head(
264
+ git_reference *branch)
265
+ {
266
+ git_reference *head;
267
+ bool is_same = false;
268
+ int error;
269
+
270
+ assert(branch);
271
+
272
+ if (!git_reference_is_branch(branch))
273
+ return false;
274
+
275
+ error = git_repository_head(&head, git_reference_owner(branch));
276
+
277
+ if (error == GIT_EORPHANEDHEAD)
278
+ return false;
279
+
280
+ if (error < 0)
281
+ return -1;
282
+
283
+ is_same = strcmp(
284
+ git_reference_name(branch),
285
+ git_reference_name(head)) == 0;
286
+
287
+ git_reference_free(head);
288
+
289
+ return is_same;
290
+ }