rugged 0.17.0.b6 → 0.17.0.b7

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -13,6 +13,7 @@
13
13
  #include "repository.h"
14
14
 
15
15
  #define GIT_CONFIG_FILENAME ".gitconfig"
16
+ #define GIT_CONFIG_FILENAME_ALT ".config/git/config"
16
17
  #define GIT_CONFIG_FILENAME_INREPO "config"
17
18
  #define GIT_CONFIG_FILENAME_SYSTEM "gitconfig"
18
19
  #define GIT_CONFIG_FILE_MODE 0666
@@ -23,11 +24,7 @@ struct git_config {
23
24
  };
24
25
 
25
26
  extern int git_config_find_global_r(git_buf *global_config_path);
27
+ extern int git_config_find_xdg_r(git_buf *system_config_path);
26
28
  extern int git_config_find_system_r(git_buf *system_config_path);
27
29
 
28
- extern int git_config_parse_bool(int *out, const char *bool_string);
29
-
30
- extern int git_config_lookup_map_value(
31
- git_cvar_map *maps, size_t map_n, const char *value, int *out);
32
-
33
30
  #endif
@@ -22,15 +22,9 @@ GIT__USE_STRMAP;
22
22
 
23
23
  typedef struct cvar_t {
24
24
  struct cvar_t *next;
25
- char *key; /* TODO: we might be able to get rid of this */
26
- char *value;
25
+ git_config_entry *entry;
27
26
  } cvar_t;
28
27
 
29
- typedef struct {
30
- struct cvar_t *head;
31
- struct cvar_t *tail;
32
- } cvar_t_list;
33
-
34
28
  #define CVAR_LIST_HEAD(list) ((list)->head)
35
29
 
36
30
  #define CVAR_LIST_TAIL(list) ((list)->tail)
@@ -84,7 +78,7 @@ typedef struct {
84
78
  char *file_path;
85
79
  } diskfile_backend;
86
80
 
87
- static int config_parse(diskfile_backend *cfg_file);
81
+ static int config_parse(diskfile_backend *cfg_file, unsigned int level);
88
82
  static int parse_variable(diskfile_backend *cfg, char **var_name, char **var_value);
89
83
  static int config_write(diskfile_backend *cfg, const char *key, const regex_t *preg, const char *value);
90
84
  static char *escape_value(const char *ptr);
@@ -100,8 +94,9 @@ static void cvar_free(cvar_t *var)
100
94
  if (var == NULL)
101
95
  return;
102
96
 
103
- git__free(var->key);
104
- git__free(var->value);
97
+ git__free((char*)var->entry->name);
98
+ git__free((char *)var->entry->value);
99
+ git__free(var->entry);
105
100
  git__free(var);
106
101
  }
107
102
 
@@ -150,7 +145,7 @@ static void free_vars(git_strmap *values)
150
145
  git_strmap_free(values);
151
146
  }
152
147
 
153
- static int config_open(git_config_file *cfg)
148
+ static int config_open(git_config_file *cfg, unsigned int level)
154
149
  {
155
150
  int res;
156
151
  diskfile_backend *b = (diskfile_backend *)cfg;
@@ -165,7 +160,7 @@ static int config_open(git_config_file *cfg)
165
160
  if (res == GIT_ENOTFOUND)
166
161
  return 0;
167
162
 
168
- if (res < 0 || config_parse(b) < 0) {
163
+ if (res < 0 || config_parse(b, level) < 0) {
169
164
  free_vars(b->values);
170
165
  b->values = NULL;
171
166
  git_buf_free(&b->reader.buffer);
@@ -191,11 +186,11 @@ static void backend_free(git_config_file *_backend)
191
186
  static int file_foreach(
192
187
  git_config_file *backend,
193
188
  const char *regexp,
194
- int (*fn)(const char *, const char *, void *),
189
+ int (*fn)(const git_config_entry *, void *),
195
190
  void *data)
196
191
  {
197
192
  diskfile_backend *b = (diskfile_backend *)backend;
198
- cvar_t *var;
193
+ cvar_t *var, *next_var;
199
194
  const char *key;
200
195
  regex_t regex;
201
196
  int result = 0;
@@ -212,13 +207,16 @@ static int file_foreach(
212
207
  }
213
208
 
214
209
  git_strmap_foreach(b->values, key, var,
215
- for (; var != NULL; var = CVAR_LIST_NEXT(var)) {
210
+ for (; var != NULL; var = next_var) {
211
+ next_var = CVAR_LIST_NEXT(var);
212
+
216
213
  /* skip non-matching keys if regexp was provided */
217
214
  if (regexp && regexec(&regex, key, 0, NULL, 0) != 0)
218
215
  continue;
219
216
 
220
217
  /* abort iterator on non-zero return value */
221
- if (fn(key, var->value, data)) {
218
+ if (fn(var->entry, data)) {
219
+ giterr_clear();
222
220
  result = GIT_EUSER;
223
221
  goto cleanup;
224
222
  }
@@ -253,11 +251,17 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
253
251
  char *tmp = NULL;
254
252
 
255
253
  git__free(key);
254
+
256
255
  if (existing->next != NULL) {
257
256
  giterr_set(GITERR_CONFIG, "Multivar incompatible with simple set");
258
257
  return -1;
259
258
  }
260
259
 
260
+ /* don't update if old and new values already match */
261
+ if ((!existing->entry->value && !value) ||
262
+ (existing->entry->value && value && !strcmp(existing->entry->value, value)))
263
+ return 0;
264
+
261
265
  if (value) {
262
266
  tmp = git__strdup(value);
263
267
  GITERR_CHECK_ALLOC(tmp);
@@ -265,10 +269,10 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
265
269
  GITERR_CHECK_ALLOC(esc_value);
266
270
  }
267
271
 
268
- git__free(existing->value);
269
- existing->value = tmp;
272
+ git__free((void *)existing->entry->value);
273
+ existing->entry->value = tmp;
270
274
 
271
- ret = config_write(b, existing->key, NULL, esc_value);
275
+ ret = config_write(b, existing->entry->name, NULL, esc_value);
272
276
 
273
277
  git__free(esc_value);
274
278
  return ret;
@@ -276,15 +280,17 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
276
280
 
277
281
  var = git__malloc(sizeof(cvar_t));
278
282
  GITERR_CHECK_ALLOC(var);
279
-
280
283
  memset(var, 0x0, sizeof(cvar_t));
284
+ var->entry = git__malloc(sizeof(git_config_entry));
285
+ GITERR_CHECK_ALLOC(var->entry);
286
+ memset(var->entry, 0x0, sizeof(git_config_entry));
281
287
 
282
- var->key = key;
283
- var->value = NULL;
288
+ var->entry->name = key;
289
+ var->entry->value = NULL;
284
290
 
285
291
  if (value) {
286
- var->value = git__strdup(value);
287
- GITERR_CHECK_ALLOC(var->value);
292
+ var->entry->value = git__strdup(value);
293
+ GITERR_CHECK_ALLOC(var->entry->value);
288
294
  esc_value = escape_value(value);
289
295
  GITERR_CHECK_ALLOC(esc_value);
290
296
  }
@@ -308,7 +314,7 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
308
314
  /*
309
315
  * Internal function that actually gets the value in string form
310
316
  */
311
- static int config_get(git_config_file *cfg, const char *name, const char **out)
317
+ static int config_get(git_config_file *cfg, const char *name, const git_config_entry **out)
312
318
  {
313
319
  diskfile_backend *b = (diskfile_backend *)cfg;
314
320
  char *key;
@@ -324,7 +330,7 @@ static int config_get(git_config_file *cfg, const char *name, const char **out)
324
330
  if (!git_strmap_valid_index(b->values, pos))
325
331
  return GIT_ENOTFOUND;
326
332
 
327
- *out = ((cvar_t *)git_strmap_value_at(b->values, pos))->value;
333
+ *out = ((cvar_t *)git_strmap_value_at(b->values, pos))->entry;
328
334
 
329
335
  return 0;
330
336
  }
@@ -333,7 +339,7 @@ static int config_get_multivar(
333
339
  git_config_file *cfg,
334
340
  const char *name,
335
341
  const char *regex_str,
336
- int (*fn)(const char *, void *),
342
+ int (*fn)(const git_config_entry *, void *),
337
343
  void *data)
338
344
  {
339
345
  cvar_t *var;
@@ -367,10 +373,10 @@ static int config_get_multivar(
367
373
  /* and throw the callback only on the variables that
368
374
  * match the regex */
369
375
  do {
370
- if (regexec(&regex, var->value, 0, NULL, 0) == 0) {
376
+ if (regexec(&regex, var->entry->value, 0, NULL, 0) == 0) {
371
377
  /* early termination by the user is not an error;
372
378
  * just break and return successfully */
373
- if (fn(var->value, data) < 0)
379
+ if (fn(var->entry, data) < 0)
374
380
  break;
375
381
  }
376
382
 
@@ -382,7 +388,7 @@ static int config_get_multivar(
382
388
  do {
383
389
  /* early termination by the user is not an error;
384
390
  * just break and return successfully */
385
- if (fn(var->value, data) < 0)
391
+ if (fn(var->entry, data) < 0)
386
392
  break;
387
393
 
388
394
  var = var->next;
@@ -425,12 +431,12 @@ static int config_set_multivar(
425
431
  }
426
432
 
427
433
  for (;;) {
428
- if (regexec(&preg, var->value, 0, NULL, 0) == 0) {
434
+ if (regexec(&preg, var->entry->value, 0, NULL, 0) == 0) {
429
435
  char *tmp = git__strdup(value);
430
436
  GITERR_CHECK_ALLOC(tmp);
431
437
 
432
- git__free(var->value);
433
- var->value = tmp;
438
+ git__free((void *)var->entry->value);
439
+ var->entry->value = tmp;
434
440
  replaced = 1;
435
441
  }
436
442
 
@@ -444,14 +450,18 @@ static int config_set_multivar(
444
450
  if (!replaced) {
445
451
  newvar = git__malloc(sizeof(cvar_t));
446
452
  GITERR_CHECK_ALLOC(newvar);
447
-
448
453
  memset(newvar, 0x0, sizeof(cvar_t));
454
+ newvar->entry = git__malloc(sizeof(git_config_entry));
455
+ GITERR_CHECK_ALLOC(newvar->entry);
456
+ memset(newvar->entry, 0x0, sizeof(git_config_entry));
457
+
458
+ newvar->entry->name = git__strdup(var->entry->name);
459
+ GITERR_CHECK_ALLOC(newvar->entry->name);
449
460
 
450
- newvar->key = git__strdup(var->key);
451
- GITERR_CHECK_ALLOC(newvar->key);
461
+ newvar->entry->value = git__strdup(value);
462
+ GITERR_CHECK_ALLOC(newvar->entry->value);
452
463
 
453
- newvar->value = git__strdup(value);
454
- GITERR_CHECK_ALLOC(newvar->value);
464
+ newvar->entry->level = var->entry->level;
455
465
 
456
466
  var->next = newvar;
457
467
  }
@@ -492,7 +502,7 @@ static int config_delete(git_config_file *cfg, const char *name)
492
502
 
493
503
  git_strmap_delete_at(b->values, pos);
494
504
 
495
- result = config_write(b, var->key, NULL, NULL);
505
+ result = config_write(b, var->entry->name, NULL, NULL);
496
506
 
497
507
  cvar_free(var);
498
508
  return result;
@@ -811,7 +821,7 @@ fail_parse:
811
821
 
812
822
  static int skip_bom(diskfile_backend *cfg)
813
823
  {
814
- static const char utf8_bom[] = "\xef\xbb\xbf";
824
+ static const char utf8_bom[] = { '\xef', '\xbb', '\xbf' };
815
825
 
816
826
  if (cfg->reader.buffer.size < sizeof(utf8_bom))
817
827
  return 0;
@@ -889,7 +899,7 @@ static int strip_comments(char *line, int in_quotes)
889
899
  return quote_count;
890
900
  }
891
901
 
892
- static int config_parse(diskfile_backend *cfg_file)
902
+ static int config_parse(diskfile_backend *cfg_file, unsigned int level)
893
903
  {
894
904
  int c;
895
905
  char *current_section = NULL;
@@ -937,8 +947,10 @@ static int config_parse(diskfile_backend *cfg_file)
937
947
 
938
948
  var = git__malloc(sizeof(cvar_t));
939
949
  GITERR_CHECK_ALLOC(var);
940
-
941
950
  memset(var, 0x0, sizeof(cvar_t));
951
+ var->entry = git__malloc(sizeof(git_config_entry));
952
+ GITERR_CHECK_ALLOC(var->entry);
953
+ memset(var->entry, 0x0, sizeof(git_config_entry));
942
954
 
943
955
  git__strtolower(var_name);
944
956
  git_buf_printf(&buf, "%s.%s", current_section, var_name);
@@ -947,13 +959,14 @@ static int config_parse(diskfile_backend *cfg_file)
947
959
  if (git_buf_oom(&buf))
948
960
  return -1;
949
961
 
950
- var->key = git_buf_detach(&buf);
951
- var->value = var_value;
962
+ var->entry->name = git_buf_detach(&buf);
963
+ var->entry->value = var_value;
964
+ var->entry->level = level;
952
965
 
953
966
  /* Add or append the new config option */
954
- pos = git_strmap_lookup_index(cfg_file->values, var->key);
967
+ pos = git_strmap_lookup_index(cfg_file->values, var->entry->name);
955
968
  if (!git_strmap_valid_index(cfg_file->values, pos)) {
956
- git_strmap_insert(cfg_file->values, var->key, var, result);
969
+ git_strmap_insert(cfg_file->values, var->entry->name, var, result);
957
970
  if (result < 0)
958
971
  break;
959
972
  result = 0;
@@ -1173,6 +1186,10 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
1173
1186
  goto rewrite_fail;
1174
1187
  }
1175
1188
 
1189
+ /* If we are here, there is at least a section line */
1190
+ if (*(cfg->reader.buffer.ptr + cfg->reader.buffer.size - 1) != '\n')
1191
+ git_filebuf_write(&file, "\n", 1);
1192
+
1176
1193
  git_filebuf_printf(&file, "\t%s = %s\n", name, value);
1177
1194
  }
1178
1195
  }
@@ -9,9 +9,9 @@
9
9
 
10
10
  #include "git2/config.h"
11
11
 
12
- GIT_INLINE(int) git_config_file_open(git_config_file *cfg)
12
+ GIT_INLINE(int) git_config_file_open(git_config_file *cfg, unsigned int level)
13
13
  {
14
- return cfg->open(cfg);
14
+ return cfg->open(cfg, level);
15
15
  }
16
16
 
17
17
  GIT_INLINE(void) git_config_file_free(git_config_file *cfg)
@@ -19,15 +19,27 @@ GIT_INLINE(void) git_config_file_free(git_config_file *cfg)
19
19
  cfg->free(cfg);
20
20
  }
21
21
 
22
+ GIT_INLINE(int) git_config_file_get_string(
23
+ const git_config_entry **out, git_config_file *cfg, const char *name)
24
+ {
25
+ return cfg->get(cfg, name, out);
26
+ }
27
+
22
28
  GIT_INLINE(int) git_config_file_set_string(
23
29
  git_config_file *cfg, const char *name, const char *value)
24
30
  {
25
31
  return cfg->set(cfg, name, value);
26
32
  }
27
33
 
34
+ GIT_INLINE(int) git_config_file_delete(
35
+ git_config_file *cfg, const char *name)
36
+ {
37
+ return cfg->del(cfg, name);
38
+ }
39
+
28
40
  GIT_INLINE(int) git_config_file_foreach(
29
41
  git_config_file *cfg,
30
- int (*fn)(const char *key, const char *value, void *data),
42
+ int (*fn)(const git_config_entry *entry, void *data),
31
43
  void *data)
32
44
  {
33
45
  return cfg->foreach(cfg, NULL, fn, data);
@@ -36,7 +48,7 @@ GIT_INLINE(int) git_config_file_foreach(
36
48
  GIT_INLINE(int) git_config_file_foreach_match(
37
49
  git_config_file *cfg,
38
50
  const char *regexp,
39
- int (*fn)(const char *key, const char *value, void *data),
51
+ int (*fn)(const git_config_entry *entry, void *data),
40
52
  void *data)
41
53
  {
42
54
  return cfg->foreach(cfg, regexp, fn, data);
@@ -263,8 +263,9 @@ static int crlf_apply_to_workdir(git_filter *self, git_buf *dest, const git_buf
263
263
  return convert_line_endings(dest, source, workdir_ending);
264
264
  }
265
265
 
266
- static int find_and_add_filter(git_vector *filters, git_repository *repo, const char *path,
267
- int (*apply)(struct git_filter *self, git_buf *dest, const git_buf *source))
266
+ static int find_and_add_filter(
267
+ git_vector *filters, git_repository *repo, const char *path,
268
+ int (*apply)(struct git_filter *self, git_buf *dest, const git_buf *source))
268
269
  {
269
270
  struct crlf_attrs ca;
270
271
  struct crlf_filter *filter;
@@ -276,7 +277,7 @@ static int find_and_add_filter(git_vector *filters, git_repository *repo, const
276
277
 
277
278
  /*
278
279
  * Use the core Git logic to see if we should perform CRLF for this file
279
- * based on its attributes & the value of `core.auto_crlf`
280
+ * based on its attributes & the value of `core.autocrlf`
280
281
  */
281
282
  ca.crlf_action = crlf_input_action(&ca);
282
283
 
@@ -0,0 +1,491 @@
1
+ /*
2
+ * diff-delta.c: generate a delta between two buffers
3
+ *
4
+ * This code was greatly inspired by parts of LibXDiff from Davide Libenzi
5
+ * http://www.xmailserver.org/xdiff-lib.html
6
+ *
7
+ * Rewritten for GIT by Nicolas Pitre <nico@fluxnic.net>, (C) 2005-2007
8
+ *
9
+ * Modified for libgit2 by Michael Schubert <schu@schu.io>, (C) 2012
10
+ *
11
+ * This code is free software; you can redistribute it and/or modify
12
+ * it under the terms of the GNU General Public License version 2 as
13
+ * published by the Free Software Foundation.
14
+ */
15
+
16
+ #include "delta.h"
17
+
18
+ /* maximum hash entry list for the same hash bucket */
19
+ #define HASH_LIMIT 64
20
+
21
+ #define RABIN_SHIFT 23
22
+ #define RABIN_WINDOW 16
23
+
24
+ static const unsigned int T[256] = {
25
+ 0x00000000, 0xab59b4d1, 0x56b369a2, 0xfdeadd73, 0x063f6795, 0xad66d344,
26
+ 0x508c0e37, 0xfbd5bae6, 0x0c7ecf2a, 0xa7277bfb, 0x5acda688, 0xf1941259,
27
+ 0x0a41a8bf, 0xa1181c6e, 0x5cf2c11d, 0xf7ab75cc, 0x18fd9e54, 0xb3a42a85,
28
+ 0x4e4ef7f6, 0xe5174327, 0x1ec2f9c1, 0xb59b4d10, 0x48719063, 0xe32824b2,
29
+ 0x1483517e, 0xbfdae5af, 0x423038dc, 0xe9698c0d, 0x12bc36eb, 0xb9e5823a,
30
+ 0x440f5f49, 0xef56eb98, 0x31fb3ca8, 0x9aa28879, 0x6748550a, 0xcc11e1db,
31
+ 0x37c45b3d, 0x9c9defec, 0x6177329f, 0xca2e864e, 0x3d85f382, 0x96dc4753,
32
+ 0x6b369a20, 0xc06f2ef1, 0x3bba9417, 0x90e320c6, 0x6d09fdb5, 0xc6504964,
33
+ 0x2906a2fc, 0x825f162d, 0x7fb5cb5e, 0xd4ec7f8f, 0x2f39c569, 0x846071b8,
34
+ 0x798aaccb, 0xd2d3181a, 0x25786dd6, 0x8e21d907, 0x73cb0474, 0xd892b0a5,
35
+ 0x23470a43, 0x881ebe92, 0x75f463e1, 0xdeadd730, 0x63f67950, 0xc8afcd81,
36
+ 0x354510f2, 0x9e1ca423, 0x65c91ec5, 0xce90aa14, 0x337a7767, 0x9823c3b6,
37
+ 0x6f88b67a, 0xc4d102ab, 0x393bdfd8, 0x92626b09, 0x69b7d1ef, 0xc2ee653e,
38
+ 0x3f04b84d, 0x945d0c9c, 0x7b0be704, 0xd05253d5, 0x2db88ea6, 0x86e13a77,
39
+ 0x7d348091, 0xd66d3440, 0x2b87e933, 0x80de5de2, 0x7775282e, 0xdc2c9cff,
40
+ 0x21c6418c, 0x8a9ff55d, 0x714a4fbb, 0xda13fb6a, 0x27f92619, 0x8ca092c8,
41
+ 0x520d45f8, 0xf954f129, 0x04be2c5a, 0xafe7988b, 0x5432226d, 0xff6b96bc,
42
+ 0x02814bcf, 0xa9d8ff1e, 0x5e738ad2, 0xf52a3e03, 0x08c0e370, 0xa39957a1,
43
+ 0x584ced47, 0xf3155996, 0x0eff84e5, 0xa5a63034, 0x4af0dbac, 0xe1a96f7d,
44
+ 0x1c43b20e, 0xb71a06df, 0x4ccfbc39, 0xe79608e8, 0x1a7cd59b, 0xb125614a,
45
+ 0x468e1486, 0xedd7a057, 0x103d7d24, 0xbb64c9f5, 0x40b17313, 0xebe8c7c2,
46
+ 0x16021ab1, 0xbd5bae60, 0x6cb54671, 0xc7ecf2a0, 0x3a062fd3, 0x915f9b02,
47
+ 0x6a8a21e4, 0xc1d39535, 0x3c394846, 0x9760fc97, 0x60cb895b, 0xcb923d8a,
48
+ 0x3678e0f9, 0x9d215428, 0x66f4eece, 0xcdad5a1f, 0x3047876c, 0x9b1e33bd,
49
+ 0x7448d825, 0xdf116cf4, 0x22fbb187, 0x89a20556, 0x7277bfb0, 0xd92e0b61,
50
+ 0x24c4d612, 0x8f9d62c3, 0x7836170f, 0xd36fa3de, 0x2e857ead, 0x85dcca7c,
51
+ 0x7e09709a, 0xd550c44b, 0x28ba1938, 0x83e3ade9, 0x5d4e7ad9, 0xf617ce08,
52
+ 0x0bfd137b, 0xa0a4a7aa, 0x5b711d4c, 0xf028a99d, 0x0dc274ee, 0xa69bc03f,
53
+ 0x5130b5f3, 0xfa690122, 0x0783dc51, 0xacda6880, 0x570fd266, 0xfc5666b7,
54
+ 0x01bcbbc4, 0xaae50f15, 0x45b3e48d, 0xeeea505c, 0x13008d2f, 0xb85939fe,
55
+ 0x438c8318, 0xe8d537c9, 0x153feaba, 0xbe665e6b, 0x49cd2ba7, 0xe2949f76,
56
+ 0x1f7e4205, 0xb427f6d4, 0x4ff24c32, 0xe4abf8e3, 0x19412590, 0xb2189141,
57
+ 0x0f433f21, 0xa41a8bf0, 0x59f05683, 0xf2a9e252, 0x097c58b4, 0xa225ec65,
58
+ 0x5fcf3116, 0xf49685c7, 0x033df00b, 0xa86444da, 0x558e99a9, 0xfed72d78,
59
+ 0x0502979e, 0xae5b234f, 0x53b1fe3c, 0xf8e84aed, 0x17bea175, 0xbce715a4,
60
+ 0x410dc8d7, 0xea547c06, 0x1181c6e0, 0xbad87231, 0x4732af42, 0xec6b1b93,
61
+ 0x1bc06e5f, 0xb099da8e, 0x4d7307fd, 0xe62ab32c, 0x1dff09ca, 0xb6a6bd1b,
62
+ 0x4b4c6068, 0xe015d4b9, 0x3eb80389, 0x95e1b758, 0x680b6a2b, 0xc352defa,
63
+ 0x3887641c, 0x93ded0cd, 0x6e340dbe, 0xc56db96f, 0x32c6cca3, 0x999f7872,
64
+ 0x6475a501, 0xcf2c11d0, 0x34f9ab36, 0x9fa01fe7, 0x624ac294, 0xc9137645,
65
+ 0x26459ddd, 0x8d1c290c, 0x70f6f47f, 0xdbaf40ae, 0x207afa48, 0x8b234e99,
66
+ 0x76c993ea, 0xdd90273b, 0x2a3b52f7, 0x8162e626, 0x7c883b55, 0xd7d18f84,
67
+ 0x2c043562, 0x875d81b3, 0x7ab75cc0, 0xd1eee811
68
+ };
69
+
70
+ static const unsigned int U[256] = {
71
+ 0x00000000, 0x7eb5200d, 0x5633f4cb, 0x2886d4c6, 0x073e5d47, 0x798b7d4a,
72
+ 0x510da98c, 0x2fb88981, 0x0e7cba8e, 0x70c99a83, 0x584f4e45, 0x26fa6e48,
73
+ 0x0942e7c9, 0x77f7c7c4, 0x5f711302, 0x21c4330f, 0x1cf9751c, 0x624c5511,
74
+ 0x4aca81d7, 0x347fa1da, 0x1bc7285b, 0x65720856, 0x4df4dc90, 0x3341fc9d,
75
+ 0x1285cf92, 0x6c30ef9f, 0x44b63b59, 0x3a031b54, 0x15bb92d5, 0x6b0eb2d8,
76
+ 0x4388661e, 0x3d3d4613, 0x39f2ea38, 0x4747ca35, 0x6fc11ef3, 0x11743efe,
77
+ 0x3eccb77f, 0x40799772, 0x68ff43b4, 0x164a63b9, 0x378e50b6, 0x493b70bb,
78
+ 0x61bda47d, 0x1f088470, 0x30b00df1, 0x4e052dfc, 0x6683f93a, 0x1836d937,
79
+ 0x250b9f24, 0x5bbebf29, 0x73386bef, 0x0d8d4be2, 0x2235c263, 0x5c80e26e,
80
+ 0x740636a8, 0x0ab316a5, 0x2b7725aa, 0x55c205a7, 0x7d44d161, 0x03f1f16c,
81
+ 0x2c4978ed, 0x52fc58e0, 0x7a7a8c26, 0x04cfac2b, 0x73e5d470, 0x0d50f47d,
82
+ 0x25d620bb, 0x5b6300b6, 0x74db8937, 0x0a6ea93a, 0x22e87dfc, 0x5c5d5df1,
83
+ 0x7d996efe, 0x032c4ef3, 0x2baa9a35, 0x551fba38, 0x7aa733b9, 0x041213b4,
84
+ 0x2c94c772, 0x5221e77f, 0x6f1ca16c, 0x11a98161, 0x392f55a7, 0x479a75aa,
85
+ 0x6822fc2b, 0x1697dc26, 0x3e1108e0, 0x40a428ed, 0x61601be2, 0x1fd53bef,
86
+ 0x3753ef29, 0x49e6cf24, 0x665e46a5, 0x18eb66a8, 0x306db26e, 0x4ed89263,
87
+ 0x4a173e48, 0x34a21e45, 0x1c24ca83, 0x6291ea8e, 0x4d29630f, 0x339c4302,
88
+ 0x1b1a97c4, 0x65afb7c9, 0x446b84c6, 0x3adea4cb, 0x1258700d, 0x6ced5000,
89
+ 0x4355d981, 0x3de0f98c, 0x15662d4a, 0x6bd30d47, 0x56ee4b54, 0x285b6b59,
90
+ 0x00ddbf9f, 0x7e689f92, 0x51d01613, 0x2f65361e, 0x07e3e2d8, 0x7956c2d5,
91
+ 0x5892f1da, 0x2627d1d7, 0x0ea10511, 0x7014251c, 0x5facac9d, 0x21198c90,
92
+ 0x099f5856, 0x772a785b, 0x4c921c31, 0x32273c3c, 0x1aa1e8fa, 0x6414c8f7,
93
+ 0x4bac4176, 0x3519617b, 0x1d9fb5bd, 0x632a95b0, 0x42eea6bf, 0x3c5b86b2,
94
+ 0x14dd5274, 0x6a687279, 0x45d0fbf8, 0x3b65dbf5, 0x13e30f33, 0x6d562f3e,
95
+ 0x506b692d, 0x2ede4920, 0x06589de6, 0x78edbdeb, 0x5755346a, 0x29e01467,
96
+ 0x0166c0a1, 0x7fd3e0ac, 0x5e17d3a3, 0x20a2f3ae, 0x08242768, 0x76910765,
97
+ 0x59298ee4, 0x279caee9, 0x0f1a7a2f, 0x71af5a22, 0x7560f609, 0x0bd5d604,
98
+ 0x235302c2, 0x5de622cf, 0x725eab4e, 0x0ceb8b43, 0x246d5f85, 0x5ad87f88,
99
+ 0x7b1c4c87, 0x05a96c8a, 0x2d2fb84c, 0x539a9841, 0x7c2211c0, 0x029731cd,
100
+ 0x2a11e50b, 0x54a4c506, 0x69998315, 0x172ca318, 0x3faa77de, 0x411f57d3,
101
+ 0x6ea7de52, 0x1012fe5f, 0x38942a99, 0x46210a94, 0x67e5399b, 0x19501996,
102
+ 0x31d6cd50, 0x4f63ed5d, 0x60db64dc, 0x1e6e44d1, 0x36e89017, 0x485db01a,
103
+ 0x3f77c841, 0x41c2e84c, 0x69443c8a, 0x17f11c87, 0x38499506, 0x46fcb50b,
104
+ 0x6e7a61cd, 0x10cf41c0, 0x310b72cf, 0x4fbe52c2, 0x67388604, 0x198da609,
105
+ 0x36352f88, 0x48800f85, 0x6006db43, 0x1eb3fb4e, 0x238ebd5d, 0x5d3b9d50,
106
+ 0x75bd4996, 0x0b08699b, 0x24b0e01a, 0x5a05c017, 0x728314d1, 0x0c3634dc,
107
+ 0x2df207d3, 0x534727de, 0x7bc1f318, 0x0574d315, 0x2acc5a94, 0x54797a99,
108
+ 0x7cffae5f, 0x024a8e52, 0x06852279, 0x78300274, 0x50b6d6b2, 0x2e03f6bf,
109
+ 0x01bb7f3e, 0x7f0e5f33, 0x57888bf5, 0x293dabf8, 0x08f998f7, 0x764cb8fa,
110
+ 0x5eca6c3c, 0x207f4c31, 0x0fc7c5b0, 0x7172e5bd, 0x59f4317b, 0x27411176,
111
+ 0x1a7c5765, 0x64c97768, 0x4c4fa3ae, 0x32fa83a3, 0x1d420a22, 0x63f72a2f,
112
+ 0x4b71fee9, 0x35c4dee4, 0x1400edeb, 0x6ab5cde6, 0x42331920, 0x3c86392d,
113
+ 0x133eb0ac, 0x6d8b90a1, 0x450d4467, 0x3bb8646a
114
+ };
115
+
116
+ struct index_entry {
117
+ const unsigned char *ptr;
118
+ unsigned int val;
119
+ };
120
+
121
+ struct unpacked_index_entry {
122
+ struct index_entry entry;
123
+ struct unpacked_index_entry *next;
124
+ };
125
+
126
+ struct git_delta_index {
127
+ unsigned long memsize;
128
+ const void *src_buf;
129
+ unsigned long src_size;
130
+ unsigned int hash_mask;
131
+ struct index_entry *hash[GIT_FLEX_ARRAY];
132
+ };
133
+
134
+ struct git_delta_index *
135
+ git_delta_create_index(const void *buf, unsigned long bufsize)
136
+ {
137
+ unsigned int i, hsize, hmask, entries, prev_val, *hash_count;
138
+ const unsigned char *data, *buffer = buf;
139
+ struct git_delta_index *index;
140
+ struct unpacked_index_entry *entry, **hash;
141
+ struct index_entry *packed_entry, **packed_hash;
142
+ void *mem;
143
+ unsigned long memsize;
144
+
145
+ if (!buf || !bufsize)
146
+ return NULL;
147
+
148
+ /* Determine index hash size. Note that indexing skips the
149
+ first byte to allow for optimizing the Rabin's polynomial
150
+ initialization in create_delta(). */
151
+ entries = (bufsize - 1) / RABIN_WINDOW;
152
+ if (bufsize >= 0xffffffffUL) {
153
+ /*
154
+ * Current delta format can't encode offsets into
155
+ * reference buffer with more than 32 bits.
156
+ */
157
+ entries = 0xfffffffeU / RABIN_WINDOW;
158
+ }
159
+ hsize = entries / 4;
160
+ for (i = 4; (1u << i) < hsize && i < 31; i++);
161
+ hsize = 1 << i;
162
+ hmask = hsize - 1;
163
+
164
+ /* allocate lookup index */
165
+ memsize = sizeof(*hash) * hsize +
166
+ sizeof(*entry) * entries;
167
+ mem = git__malloc(memsize);
168
+ if (!mem)
169
+ return NULL;
170
+ hash = mem;
171
+ mem = hash + hsize;
172
+ entry = mem;
173
+
174
+ memset(hash, 0, hsize * sizeof(*hash));
175
+
176
+ /* allocate an array to count hash entries */
177
+ hash_count = calloc(hsize, sizeof(*hash_count));
178
+ if (!hash_count) {
179
+ git__free(hash);
180
+ return NULL;
181
+ }
182
+
183
+ /* then populate the index */
184
+ prev_val = ~0;
185
+ for (data = buffer + entries * RABIN_WINDOW - RABIN_WINDOW;
186
+ data >= buffer;
187
+ data -= RABIN_WINDOW) {
188
+ unsigned int val = 0;
189
+ for (i = 1; i <= RABIN_WINDOW; i++)
190
+ val = ((val << 8) | data[i]) ^ T[val >> RABIN_SHIFT];
191
+ if (val == prev_val) {
192
+ /* keep the lowest of consecutive identical blocks */
193
+ entry[-1].entry.ptr = data + RABIN_WINDOW;
194
+ --entries;
195
+ } else {
196
+ prev_val = val;
197
+ i = val & hmask;
198
+ entry->entry.ptr = data + RABIN_WINDOW;
199
+ entry->entry.val = val;
200
+ entry->next = hash[i];
201
+ hash[i] = entry++;
202
+ hash_count[i]++;
203
+ }
204
+ }
205
+
206
+ /*
207
+ * Determine a limit on the number of entries in the same hash
208
+ * bucket. This guards us against pathological data sets causing
209
+ * really bad hash distribution with most entries in the same hash
210
+ * bucket that would bring us to O(m*n) computing costs (m and n
211
+ * corresponding to reference and target buffer sizes).
212
+ *
213
+ * Make sure none of the hash buckets has more entries than
214
+ * we're willing to test. Otherwise we cull the entry list
215
+ * uniformly to still preserve a good repartition across
216
+ * the reference buffer.
217
+ */
218
+ for (i = 0; i < hsize; i++) {
219
+ int acc;
220
+
221
+ if (hash_count[i] <= HASH_LIMIT)
222
+ continue;
223
+
224
+ /* We leave exactly HASH_LIMIT entries in the bucket */
225
+ entries -= hash_count[i] - HASH_LIMIT;
226
+
227
+ entry = hash[i];
228
+ acc = 0;
229
+
230
+ /*
231
+ * Assume that this loop is gone through exactly
232
+ * HASH_LIMIT times and is entered and left with
233
+ * acc==0. So the first statement in the loop
234
+ * contributes (hash_count[i]-HASH_LIMIT)*HASH_LIMIT
235
+ * to the accumulator, and the inner loop consequently
236
+ * is run (hash_count[i]-HASH_LIMIT) times, removing
237
+ * one element from the list each time. Since acc
238
+ * balances out to 0 at the final run, the inner loop
239
+ * body can't be left with entry==NULL. So we indeed
240
+ * encounter entry==NULL in the outer loop only.
241
+ */
242
+ do {
243
+ acc += hash_count[i] - HASH_LIMIT;
244
+ if (acc > 0) {
245
+ struct unpacked_index_entry *keep = entry;
246
+ do {
247
+ entry = entry->next;
248
+ acc -= HASH_LIMIT;
249
+ } while (acc > 0);
250
+ keep->next = entry->next;
251
+ }
252
+ entry = entry->next;
253
+ } while (entry);
254
+ }
255
+ git__free(hash_count);
256
+
257
+ /*
258
+ * Now create the packed index in array form
259
+ * rather than linked lists.
260
+ */
261
+ memsize = sizeof(*index)
262
+ + sizeof(*packed_hash) * (hsize+1)
263
+ + sizeof(*packed_entry) * entries;
264
+ mem = git__malloc(memsize);
265
+ if (!mem) {
266
+ git__free(hash);
267
+ return NULL;
268
+ }
269
+
270
+ index = mem;
271
+ index->memsize = memsize;
272
+ index->src_buf = buf;
273
+ index->src_size = bufsize;
274
+ index->hash_mask = hmask;
275
+
276
+ mem = index->hash;
277
+ packed_hash = mem;
278
+ mem = packed_hash + (hsize+1);
279
+ packed_entry = mem;
280
+
281
+ for (i = 0; i < hsize; i++) {
282
+ /*
283
+ * Coalesce all entries belonging to one linked list
284
+ * into consecutive array entries.
285
+ */
286
+ packed_hash[i] = packed_entry;
287
+ for (entry = hash[i]; entry; entry = entry->next)
288
+ *packed_entry++ = entry->entry;
289
+ }
290
+
291
+ /* Sentinel value to indicate the length of the last hash bucket */
292
+ packed_hash[hsize] = packed_entry;
293
+
294
+ assert(packed_entry - (struct index_entry *)mem == entries);
295
+ git__free(hash);
296
+
297
+ return index;
298
+ }
299
+
300
+ void git_delta_free_index(struct git_delta_index *index)
301
+ {
302
+ git__free(index);
303
+ }
304
+
305
+ unsigned long git_delta_sizeof_index(struct git_delta_index *index)
306
+ {
307
+ if (index)
308
+ return index->memsize;
309
+ else
310
+ return 0;
311
+ }
312
+
313
+ /*
314
+ * The maximum size for any opcode sequence, including the initial header
315
+ * plus Rabin window plus biggest copy.
316
+ */
317
+ #define MAX_OP_SIZE (5 + 5 + 1 + RABIN_WINDOW + 7)
318
+
319
+ void *
320
+ git_delta_create(const struct git_delta_index *index,
321
+ const void *trg_buf, unsigned long trg_size,
322
+ unsigned long *delta_size, unsigned long max_size)
323
+ {
324
+ unsigned int i, outpos, outsize, moff, msize, val;
325
+ int inscnt;
326
+ const unsigned char *ref_data, *ref_top, *data, *top;
327
+ unsigned char *out;
328
+
329
+ if (!trg_buf || !trg_size)
330
+ return NULL;
331
+
332
+ outpos = 0;
333
+ outsize = 8192;
334
+ if (max_size && outsize >= max_size)
335
+ outsize = max_size + MAX_OP_SIZE + 1;
336
+ out = git__malloc(outsize);
337
+ if (!out)
338
+ return NULL;
339
+
340
+ /* store reference buffer size */
341
+ i = index->src_size;
342
+ while (i >= 0x80) {
343
+ out[outpos++] = i | 0x80;
344
+ i >>= 7;
345
+ }
346
+ out[outpos++] = i;
347
+
348
+ /* store target buffer size */
349
+ i = trg_size;
350
+ while (i >= 0x80) {
351
+ out[outpos++] = i | 0x80;
352
+ i >>= 7;
353
+ }
354
+ out[outpos++] = i;
355
+
356
+ ref_data = index->src_buf;
357
+ ref_top = ref_data + index->src_size;
358
+ data = trg_buf;
359
+ top = (const unsigned char *) trg_buf + trg_size;
360
+
361
+ outpos++;
362
+ val = 0;
363
+ for (i = 0; i < RABIN_WINDOW && data < top; i++, data++) {
364
+ out[outpos++] = *data;
365
+ val = ((val << 8) | *data) ^ T[val >> RABIN_SHIFT];
366
+ }
367
+ inscnt = i;
368
+
369
+ moff = 0;
370
+ msize = 0;
371
+ while (data < top) {
372
+ if (msize < 4096) {
373
+ struct index_entry *entry;
374
+ val ^= U[data[-RABIN_WINDOW]];
375
+ val = ((val << 8) | *data) ^ T[val >> RABIN_SHIFT];
376
+ i = val & index->hash_mask;
377
+ for (entry = index->hash[i]; entry < index->hash[i+1]; entry++) {
378
+ const unsigned char *ref = entry->ptr;
379
+ const unsigned char *src = data;
380
+ unsigned int ref_size = ref_top - ref;
381
+ if (entry->val != val)
382
+ continue;
383
+ if (ref_size > (unsigned int)(top - src))
384
+ ref_size = top - src;
385
+ if (ref_size <= msize)
386
+ break;
387
+ while (ref_size-- && *src++ == *ref)
388
+ ref++;
389
+ if (msize < (unsigned int)(ref - entry->ptr)) {
390
+ /* this is our best match so far */
391
+ msize = ref - entry->ptr;
392
+ moff = entry->ptr - ref_data;
393
+ if (msize >= 4096) /* good enough */
394
+ break;
395
+ }
396
+ }
397
+ }
398
+
399
+ if (msize < 4) {
400
+ if (!inscnt)
401
+ outpos++;
402
+ out[outpos++] = *data++;
403
+ inscnt++;
404
+ if (inscnt == 0x7f) {
405
+ out[outpos - inscnt - 1] = inscnt;
406
+ inscnt = 0;
407
+ }
408
+ msize = 0;
409
+ } else {
410
+ unsigned int left;
411
+ unsigned char *op;
412
+
413
+ if (inscnt) {
414
+ while (moff && ref_data[moff-1] == data[-1]) {
415
+ /* we can match one byte back */
416
+ msize++;
417
+ moff--;
418
+ data--;
419
+ outpos--;
420
+ if (--inscnt)
421
+ continue;
422
+ outpos--; /* remove count slot */
423
+ inscnt--; /* make it -1 */
424
+ break;
425
+ }
426
+ out[outpos - inscnt - 1] = inscnt;
427
+ inscnt = 0;
428
+ }
429
+
430
+ /* A copy op is currently limited to 64KB (pack v2) */
431
+ left = (msize < 0x10000) ? 0 : (msize - 0x10000);
432
+ msize -= left;
433
+
434
+ op = out + outpos++;
435
+ i = 0x80;
436
+
437
+ if (moff & 0x000000ff)
438
+ out[outpos++] = moff >> 0, i |= 0x01;
439
+ if (moff & 0x0000ff00)
440
+ out[outpos++] = moff >> 8, i |= 0x02;
441
+ if (moff & 0x00ff0000)
442
+ out[outpos++] = moff >> 16, i |= 0x04;
443
+ if (moff & 0xff000000)
444
+ out[outpos++] = moff >> 24, i |= 0x08;
445
+
446
+ if (msize & 0x00ff)
447
+ out[outpos++] = msize >> 0, i |= 0x10;
448
+ if (msize & 0xff00)
449
+ out[outpos++] = msize >> 8, i |= 0x20;
450
+
451
+ *op = i;
452
+
453
+ data += msize;
454
+ moff += msize;
455
+ msize = left;
456
+
457
+ if (msize < 4096) {
458
+ int j;
459
+ val = 0;
460
+ for (j = -RABIN_WINDOW; j < 0; j++)
461
+ val = ((val << 8) | data[j])
462
+ ^ T[val >> RABIN_SHIFT];
463
+ }
464
+ }
465
+
466
+ if (outpos >= outsize - MAX_OP_SIZE) {
467
+ void *tmp = out;
468
+ outsize = outsize * 3 / 2;
469
+ if (max_size && outsize >= max_size)
470
+ outsize = max_size + MAX_OP_SIZE + 1;
471
+ if (max_size && outpos > max_size)
472
+ break;
473
+ out = git__realloc(out, outsize);
474
+ if (!out) {
475
+ git__free(tmp);
476
+ return NULL;
477
+ }
478
+ }
479
+ }
480
+
481
+ if (inscnt)
482
+ out[outpos - inscnt - 1] = inscnt;
483
+
484
+ if (max_size && outpos > max_size) {
485
+ git__free(out);
486
+ return NULL;
487
+ }
488
+
489
+ *delta_size = outpos;
490
+ return out;
491
+ }