rugged 0.25.0b5 → 0.25.0b6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/rugged_patch.c +77 -17
  3. data/lib/rugged/version.rb +1 -1
  4. data/vendor/libgit2/CMakeLists.txt +8 -6
  5. data/vendor/libgit2/include/git2/checkout.h +7 -0
  6. data/vendor/libgit2/include/git2/common.h +1 -0
  7. data/vendor/libgit2/include/git2/diff.h +54 -7
  8. data/vendor/libgit2/include/git2/errors.h +2 -1
  9. data/vendor/libgit2/include/git2/index.h +25 -0
  10. data/vendor/libgit2/include/git2/pack.h +4 -4
  11. data/vendor/libgit2/include/git2/repository.h +20 -1
  12. data/vendor/libgit2/include/git2/submodule.h +11 -3
  13. data/vendor/libgit2/include/git2/sys/odb_backend.h +11 -0
  14. data/vendor/libgit2/src/apply.c +369 -0
  15. data/vendor/libgit2/src/apply.h +21 -0
  16. data/vendor/libgit2/src/array.h +0 -1
  17. data/vendor/libgit2/src/blame_git.c +18 -8
  18. data/vendor/libgit2/src/buffer.c +252 -20
  19. data/vendor/libgit2/src/buffer.h +8 -0
  20. data/vendor/libgit2/src/checkout.c +7 -1
  21. data/vendor/libgit2/src/clone.c +0 -8
  22. data/vendor/libgit2/src/common.h +1 -1
  23. data/vendor/libgit2/src/crlf.c +1 -0
  24. data/vendor/libgit2/src/delta.c +238 -62
  25. data/vendor/libgit2/src/delta.h +79 -58
  26. data/vendor/libgit2/src/diff.c +32 -1547
  27. data/vendor/libgit2/src/diff.h +12 -122
  28. data/vendor/libgit2/src/diff_driver.c +1 -2
  29. data/vendor/libgit2/src/diff_file.c +3 -0
  30. data/vendor/libgit2/src/diff_generate.c +1611 -0
  31. data/vendor/libgit2/src/diff_generate.h +123 -0
  32. data/vendor/libgit2/src/diff_parse.c +105 -0
  33. data/vendor/libgit2/src/diff_print.c +259 -142
  34. data/vendor/libgit2/src/diff_stats.c +3 -2
  35. data/vendor/libgit2/src/diff_tform.c +1 -0
  36. data/vendor/libgit2/src/diff_tform.h +22 -0
  37. data/vendor/libgit2/src/diff_xdiff.c +9 -9
  38. data/vendor/libgit2/src/diff_xdiff.h +5 -5
  39. data/vendor/libgit2/src/fileops.c +13 -0
  40. data/vendor/libgit2/src/fileops.h +6 -0
  41. data/vendor/libgit2/src/global.c +9 -8
  42. data/vendor/libgit2/src/ignore.c +45 -16
  43. data/vendor/libgit2/src/index.c +161 -47
  44. data/vendor/libgit2/src/index.h +2 -0
  45. data/vendor/libgit2/src/merge.c +2 -0
  46. data/vendor/libgit2/src/mwindow.c +8 -19
  47. data/vendor/libgit2/src/mwindow.h +1 -2
  48. data/vendor/libgit2/src/odb.c +46 -10
  49. data/vendor/libgit2/src/odb_loose.c +19 -1
  50. data/vendor/libgit2/src/odb_pack.c +27 -4
  51. data/vendor/libgit2/src/pack-objects.c +106 -77
  52. data/vendor/libgit2/src/pack-objects.h +13 -12
  53. data/vendor/libgit2/src/pack.c +4 -3
  54. data/vendor/libgit2/src/pack.h +2 -0
  55. data/vendor/libgit2/src/patch.c +207 -0
  56. data/vendor/libgit2/src/patch.h +66 -0
  57. data/vendor/libgit2/src/{diff_patch.c → patch_generate.c} +171 -359
  58. data/vendor/libgit2/src/patch_generate.h +66 -0
  59. data/vendor/libgit2/src/patch_parse.c +1121 -0
  60. data/vendor/libgit2/src/patch_parse.h +54 -0
  61. data/vendor/libgit2/src/path.c +19 -0
  62. data/vendor/libgit2/src/path.h +6 -0
  63. data/vendor/libgit2/src/pool.h +5 -0
  64. data/vendor/libgit2/src/remote.c +15 -80
  65. data/vendor/libgit2/src/repository.c +227 -39
  66. data/vendor/libgit2/src/settings.c +11 -5
  67. data/vendor/libgit2/src/stash.c +1 -0
  68. data/vendor/libgit2/src/status.c +1 -0
  69. data/vendor/libgit2/src/stransport_stream.c +14 -9
  70. data/vendor/libgit2/src/submodule.c +16 -4
  71. data/vendor/libgit2/src/sysdir.c +41 -47
  72. data/vendor/libgit2/src/sysdir.h +0 -5
  73. data/vendor/libgit2/src/thread-utils.h +5 -51
  74. data/vendor/libgit2/src/transport.c +3 -5
  75. data/vendor/libgit2/src/transports/http.c +2 -3
  76. data/vendor/libgit2/src/transports/smart_pkt.c +1 -0
  77. data/vendor/libgit2/src/transports/smart_protocol.c +11 -0
  78. data/vendor/libgit2/src/transports/winhttp.c +16 -2
  79. data/vendor/libgit2/src/unix/pthread.h +54 -0
  80. data/vendor/libgit2/src/util.c +23 -5
  81. data/vendor/libgit2/src/util.h +10 -0
  82. data/vendor/libgit2/src/varint.c +44 -0
  83. data/vendor/libgit2/src/varint.h +15 -0
  84. data/vendor/libgit2/src/vector.c +42 -0
  85. data/vendor/libgit2/src/vector.h +3 -0
  86. data/vendor/libgit2/src/win32/precompiled.h +1 -1
  87. data/vendor/libgit2/src/win32/{pthread.c → thread.c} +50 -80
  88. data/vendor/libgit2/src/win32/thread.h +62 -0
  89. data/vendor/libgit2/src/zstream.c +36 -7
  90. data/vendor/libgit2/src/zstream.h +8 -1
  91. metadata +20 -9
  92. data/vendor/libgit2/src/delta-apply.c +0 -166
  93. data/vendor/libgit2/src/delta-apply.h +0 -62
  94. data/vendor/libgit2/src/diff_patch.h +0 -83
  95. data/vendor/libgit2/src/win32/pthread.h +0 -92
@@ -0,0 +1,54 @@
1
+ /*
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
+ *
4
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
5
+ * a Linking Exception. For full terms see the included COPYING file.
6
+ */
7
+ #ifndef INCLUDE_patch_parse_h__
8
+ #define INCLUDE_patch_parse_h__
9
+
10
+ typedef struct {
11
+ git_refcount rc;
12
+
13
+ /* Original content buffer */
14
+ const char *content;
15
+ size_t content_len;
16
+
17
+ git_patch_options opts;
18
+
19
+ /* The remaining (unparsed) buffer */
20
+ const char *remain;
21
+ size_t remain_len;
22
+
23
+ const char *line;
24
+ size_t line_len;
25
+ size_t line_num;
26
+ } git_patch_parse_ctx;
27
+
28
+ extern git_patch_parse_ctx *git_patch_parse_ctx_init(
29
+ const char *content,
30
+ size_t content_len,
31
+ const git_patch_options *opts);
32
+
33
+ extern void git_patch_parse_ctx_free(git_patch_parse_ctx *ctx);
34
+
35
+ /**
36
+ * Create a patch for a single file from the contents of a patch buffer.
37
+ *
38
+ * @param out The patch to be created
39
+ * @param contents The contents of a patch file
40
+ * @param contents_len The length of the patch file
41
+ * @param opts The git_patch_options
42
+ * @return 0 on success, <0 on failure.
43
+ */
44
+ extern int git_patch_from_buffer(
45
+ git_patch **out,
46
+ const char *contents,
47
+ size_t contents_len,
48
+ const git_patch_options *opts);
49
+
50
+ extern int git_patch_parse(
51
+ git_patch **out,
52
+ git_patch_parse_ctx *ctx);
53
+
54
+ #endif
@@ -306,6 +306,25 @@ int git_path_join_unrooted(
306
306
  return 0;
307
307
  }
308
308
 
309
+ void git_path_squash_slashes(git_buf *path)
310
+ {
311
+ char *p, *q;
312
+
313
+ if (path->size == 0)
314
+ return;
315
+
316
+ for (p = path->ptr, q = path->ptr; *q; p++, q++) {
317
+ *p = *q;
318
+
319
+ while (*q == '/' && *(q+1) == '/') {
320
+ path->size--;
321
+ q++;
322
+ }
323
+ }
324
+
325
+ *p = '\0';
326
+ }
327
+
309
328
  int git_path_prettify(git_buf *path_out, const char *path, const char *base)
310
329
  {
311
330
  char buf[GIT_PATH_MAX];
@@ -243,6 +243,12 @@ extern bool git_path_contains_file(git_buf *dir, const char *file);
243
243
  extern int git_path_join_unrooted(
244
244
  git_buf *path_out, const char *path, const char *base, ssize_t *root_at);
245
245
 
246
+ /**
247
+ * Removes multiple occurrences of '/' in a row, squashing them into a
248
+ * single '/'.
249
+ */
250
+ extern void git_path_squash_slashes(git_buf *path);
251
+
246
252
  /**
247
253
  * Clean up path, prepending base if it is not already rooted.
248
254
  */
@@ -35,6 +35,8 @@ typedef struct {
35
35
  uint32_t page_size; /* size of page in bytes */
36
36
  } git_pool;
37
37
 
38
+ #define GIT_POOL_INIT { NULL, 0, 0 }
39
+
38
40
  #else
39
41
 
40
42
  /**
@@ -57,6 +59,9 @@ typedef struct {
57
59
  uint32_t item_size;
58
60
  uint32_t page_size;
59
61
  } git_pool;
62
+
63
+ #define GIT_POOL_INIT { GIT_VECTOR_INIT, 0, 0 }
64
+
60
65
  #endif
61
66
 
62
67
  /**
@@ -547,53 +547,6 @@ static int lookup_remote_prune_config(git_remote *remote, git_config *config, co
547
547
  return error;
548
548
  }
549
549
 
550
- static int update_config_refspec(const git_remote *remote, git_config *config, int direction)
551
- {
552
- git_buf name = GIT_BUF_INIT;
553
- unsigned int push;
554
- const char *dir;
555
- size_t i;
556
- int error = 0;
557
- const char *cname;
558
-
559
- push = direction == GIT_DIRECTION_PUSH;
560
- dir = push ? "push" : "fetch";
561
-
562
- if (git_buf_printf(&name, "remote.%s.%s", remote->name, dir) < 0)
563
- return -1;
564
- cname = git_buf_cstr(&name);
565
-
566
- /* Clear out the existing config */
567
- while (!error)
568
- error = git_config_delete_multivar(config, cname, ".*");
569
-
570
- if (error != GIT_ENOTFOUND)
571
- return error;
572
-
573
- for (i = 0; i < remote->refspecs.length; i++) {
574
- git_refspec *spec = git_vector_get(&remote->refspecs, i);
575
-
576
- if (spec->push != push)
577
- continue;
578
-
579
- // "$^" is a unmatcheable regexp: it will not match anything at all, so
580
- // all values will be considered new and we will not replace any
581
- // present value.
582
- if ((error = git_config_set_multivar(
583
- config, cname, "$^", spec->string)) < 0) {
584
- goto cleanup;
585
- }
586
- }
587
-
588
- giterr_clear();
589
- error = 0;
590
-
591
- cleanup:
592
- git_buf_free(&name);
593
-
594
- return error;
595
- }
596
-
597
550
  const char *git_remote_name(const git_remote *remote)
598
551
  {
599
552
  assert(remote);
@@ -1423,7 +1376,11 @@ static int update_tips_for_spec(
1423
1376
  /* In autotag mode, don't overwrite any locally-existing tags */
1424
1377
  error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag,
1425
1378
  log_message);
1426
- if (error < 0 && error != GIT_EEXISTS)
1379
+
1380
+ if (error == GIT_EEXISTS)
1381
+ continue;
1382
+
1383
+ if (error < 0)
1427
1384
  goto on_error;
1428
1385
 
1429
1386
  git_reference_free(ref);
@@ -2099,34 +2056,6 @@ int git_remote_add_push(git_repository *repo, const char *remote, const char *re
2099
2056
  return write_add_refspec(repo, remote, refspec, false);
2100
2057
  }
2101
2058
 
2102
- static int set_refspecs(git_remote *remote, git_strarray *array, int push)
2103
- {
2104
- git_vector *vec = &remote->refspecs;
2105
- git_refspec *spec;
2106
- size_t i;
2107
-
2108
- /* Start by removing any refspecs of the same type */
2109
- for (i = 0; i < vec->length; i++) {
2110
- spec = git_vector_get(vec, i);
2111
- if (spec->push != push)
2112
- continue;
2113
-
2114
- git_refspec__free(spec);
2115
- git__free(spec);
2116
- git_vector_remove(vec, i);
2117
- i--;
2118
- }
2119
-
2120
- /* And now we add the new ones */
2121
-
2122
- for (i = 0; i < array->count; i++) {
2123
- if (add_refspec(remote, array->strings[i], !push) < 0)
2124
- return -1;
2125
- }
2126
-
2127
- return 0;
2128
- }
2129
-
2130
2059
  static int copy_refspecs(git_strarray *array, const git_remote *remote, unsigned int push)
2131
2060
  {
2132
2061
  size_t i;
@@ -2233,15 +2162,21 @@ static int remove_branch_config_related_entries(
2233
2162
  if (git_buf_printf(&buf, "branch.%.*s.merge", (int)branch_len, branch) < 0)
2234
2163
  break;
2235
2164
 
2236
- if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0)
2237
- break;
2165
+ if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) {
2166
+ if (error != GIT_ENOTFOUND)
2167
+ break;
2168
+ giterr_clear();
2169
+ }
2238
2170
 
2239
2171
  git_buf_clear(&buf);
2240
2172
  if (git_buf_printf(&buf, "branch.%.*s.remote", (int)branch_len, branch) < 0)
2241
2173
  break;
2242
2174
 
2243
- if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0)
2244
- break;
2175
+ if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) {
2176
+ if (error != GIT_ENOTFOUND)
2177
+ break;
2178
+ giterr_clear();
2179
+ }
2245
2180
  }
2246
2181
 
2247
2182
  if (error == GIT_ITEROVER)
@@ -264,7 +264,7 @@ cleanup:
264
264
  * the stack could remove directories name limits, but at the cost of doing
265
265
  * repeated malloc/frees inside the loop below, so let's not do it now.
266
266
  */
267
- static int find_ceiling_dir_offset(
267
+ static size_t find_ceiling_dir_offset(
268
268
  const char *path,
269
269
  const char *ceiling_directories)
270
270
  {
@@ -278,7 +278,7 @@ static int find_ceiling_dir_offset(
278
278
  min_len = (size_t)(git_path_root(path) + 1);
279
279
 
280
280
  if (ceiling_directories == NULL || min_len == 0)
281
- return (int)min_len;
281
+ return min_len;
282
282
 
283
283
  for (sep = ceil = ceiling_directories; *sep; ceil = sep + 1) {
284
284
  for (sep = ceil; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++);
@@ -305,7 +305,7 @@ static int find_ceiling_dir_offset(
305
305
  }
306
306
  }
307
307
 
308
- return (int)(max_len <= min_len ? min_len : max_len);
308
+ return (max_len <= min_len ? min_len : max_len);
309
309
  }
310
310
 
311
311
  /*
@@ -357,29 +357,50 @@ static int find_repo(
357
357
  {
358
358
  int error;
359
359
  git_buf path = GIT_BUF_INIT;
360
+ git_buf repo_link = GIT_BUF_INIT;
360
361
  struct stat st;
361
362
  dev_t initial_device = 0;
362
- bool try_with_dot_git = ((flags & GIT_REPOSITORY_OPEN_BARE) != 0);
363
- int ceiling_offset;
363
+ int min_iterations;
364
+ bool in_dot_git;
365
+ size_t ceiling_offset = 0;
364
366
 
365
367
  git_buf_free(repo_path);
366
368
 
367
- if ((error = git_path_prettify(&path, start_path, NULL)) < 0)
369
+ error = git_path_prettify(&path, start_path, NULL);
370
+ if (error < 0)
368
371
  return error;
369
372
 
370
- ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);
373
+ /* in_dot_git toggles each loop:
374
+ * /a/b/c/.git, /a/b/c, /a/b/.git, /a/b, /a/.git, /a
375
+ * With GIT_REPOSITORY_OPEN_BARE or GIT_REPOSITORY_OPEN_NO_DOTGIT, we
376
+ * assume we started with /a/b/c.git and don't append .git the first
377
+ * time through.
378
+ * min_iterations indicates the number of iterations left before going
379
+ * further counts as a search. */
380
+ if (flags & (GIT_REPOSITORY_OPEN_BARE | GIT_REPOSITORY_OPEN_NO_DOTGIT)) {
381
+ in_dot_git = true;
382
+ min_iterations = 1;
383
+ } else {
384
+ in_dot_git = false;
385
+ min_iterations = 2;
386
+ }
371
387
 
372
- if (!try_with_dot_git &&
373
- (error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
374
- return error;
388
+ for (;;) {
389
+ if (!(flags & GIT_REPOSITORY_OPEN_NO_DOTGIT)) {
390
+ if (!in_dot_git) {
391
+ error = git_buf_joinpath(&path, path.ptr, DOT_GIT);
392
+ if (error < 0)
393
+ break;
394
+ }
395
+ in_dot_git = !in_dot_git;
396
+ }
375
397
 
376
- while (!error && !git_buf_len(repo_path)) {
377
398
  if (p_stat(path.ptr, &st) == 0) {
378
399
  /* check that we have not crossed device boundaries */
379
400
  if (initial_device == 0)
380
401
  initial_device = st.st_dev;
381
402
  else if (st.st_dev != initial_device &&
382
- (flags & GIT_REPOSITORY_OPEN_CROSS_FS) == 0)
403
+ !(flags & GIT_REPOSITORY_OPEN_CROSS_FS))
383
404
  break;
384
405
 
385
406
  if (S_ISDIR(st.st_mode)) {
@@ -390,41 +411,37 @@ static int find_repo(
390
411
  }
391
412
  }
392
413
  else if (S_ISREG(st.st_mode)) {
393
- git_buf repo_link = GIT_BUF_INIT;
394
-
395
- if (!(error = read_gitfile(&repo_link, path.ptr))) {
396
- if (valid_repository_path(&repo_link)) {
397
- git_buf_swap(repo_path, &repo_link);
398
-
399
- if (link_path)
400
- error = git_buf_put(link_path,
401
- path.ptr, path.size);
402
- }
403
-
404
- git_buf_free(&repo_link);
414
+ error = read_gitfile(&repo_link, path.ptr);
415
+ if (error < 0)
405
416
  break;
417
+ if (valid_repository_path(&repo_link)) {
418
+ git_buf_swap(repo_path, &repo_link);
419
+
420
+ if (link_path)
421
+ error = git_buf_put(link_path, path.ptr, path.size);
406
422
  }
407
- git_buf_free(&repo_link);
423
+ break;
408
424
  }
409
425
  }
410
426
 
411
- /* move up one directory level */
427
+ /* Move up one directory. If we're in_dot_git, we'll search the
428
+ * parent itself next. If we're !in_dot_git, we'll search .git
429
+ * in the parent directory next (added at the top of the loop). */
412
430
  if (git_path_dirname_r(&path, path.ptr) < 0) {
413
431
  error = -1;
414
432
  break;
415
433
  }
416
434
 
417
- if (try_with_dot_git) {
418
- /* if we tried original dir with and without .git AND either hit
419
- * directory ceiling or NO_SEARCH was requested, then be done.
420
- */
421
- if (path.ptr[ceiling_offset] == '\0' ||
422
- (flags & GIT_REPOSITORY_OPEN_NO_SEARCH) != 0)
423
- break;
424
- /* otherwise look first for .git item */
425
- error = git_buf_joinpath(&path, path.ptr, DOT_GIT);
426
- }
427
- try_with_dot_git = !try_with_dot_git;
435
+ /* Once we've checked the directory (and .git if applicable),
436
+ * find the ceiling for a search. */
437
+ if (min_iterations && (--min_iterations == 0))
438
+ ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);
439
+
440
+ /* Check if we should stop searching here. */
441
+ if (min_iterations == 0
442
+ && (path.ptr[ceiling_offset] == 0
443
+ || (flags & GIT_REPOSITORY_OPEN_NO_SEARCH)))
444
+ break;
428
445
  }
429
446
 
430
447
  if (!error && parent_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) {
@@ -438,14 +455,16 @@ static int find_repo(
438
455
  return -1;
439
456
  }
440
457
 
441
- git_buf_free(&path);
442
-
458
+ /* If we didn't find the repository, and we don't have any other error
459
+ * to report, report that. */
443
460
  if (!git_buf_len(repo_path) && !error) {
444
461
  giterr_set(GITERR_REPOSITORY,
445
462
  "Could not find repository from '%s'", start_path);
446
463
  error = GIT_ENOTFOUND;
447
464
  }
448
465
 
466
+ git_buf_free(&path);
467
+ git_buf_free(&repo_link);
449
468
  return error;
450
469
  }
451
470
 
@@ -480,6 +499,172 @@ int git_repository_open_bare(
480
499
  return 0;
481
500
  }
482
501
 
502
+ static int _git_repository_open_ext_from_env(
503
+ git_repository **out,
504
+ const char *start_path)
505
+ {
506
+ git_repository *repo = NULL;
507
+ git_index *index = NULL;
508
+ git_odb *odb = NULL;
509
+ git_buf dir_buf = GIT_BUF_INIT;
510
+ git_buf ceiling_dirs_buf = GIT_BUF_INIT;
511
+ git_buf across_fs_buf = GIT_BUF_INIT;
512
+ git_buf index_file_buf = GIT_BUF_INIT;
513
+ git_buf namespace_buf = GIT_BUF_INIT;
514
+ git_buf object_dir_buf = GIT_BUF_INIT;
515
+ git_buf alts_buf = GIT_BUF_INIT;
516
+ git_buf work_tree_buf = GIT_BUF_INIT;
517
+ git_buf common_dir_buf = GIT_BUF_INIT;
518
+ const char *ceiling_dirs = NULL;
519
+ unsigned flags = 0;
520
+ int error;
521
+
522
+ if (!start_path) {
523
+ error = git__getenv(&dir_buf, "GIT_DIR");
524
+ if (error == GIT_ENOTFOUND) {
525
+ giterr_clear();
526
+ start_path = ".";
527
+ } else if (error < 0)
528
+ goto error;
529
+ else {
530
+ start_path = git_buf_cstr(&dir_buf);
531
+ flags |= GIT_REPOSITORY_OPEN_NO_SEARCH;
532
+ flags |= GIT_REPOSITORY_OPEN_NO_DOTGIT;
533
+ }
534
+ }
535
+
536
+ error = git__getenv(&ceiling_dirs_buf, "GIT_CEILING_DIRECTORIES");
537
+ if (error == GIT_ENOTFOUND)
538
+ giterr_clear();
539
+ else if (error < 0)
540
+ goto error;
541
+ else
542
+ ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
543
+
544
+ error = git__getenv(&across_fs_buf, "GIT_DISCOVERY_ACROSS_FILESYSTEM");
545
+ if (error == GIT_ENOTFOUND)
546
+ giterr_clear();
547
+ else if (error < 0)
548
+ goto error;
549
+ else {
550
+ int across_fs = 0;
551
+ error = git_config_parse_bool(&across_fs, git_buf_cstr(&across_fs_buf));
552
+ if (error < 0)
553
+ goto error;
554
+ if (across_fs)
555
+ flags |= GIT_REPOSITORY_OPEN_CROSS_FS;
556
+ }
557
+
558
+ error = git__getenv(&index_file_buf, "GIT_INDEX_FILE");
559
+ if (error == GIT_ENOTFOUND)
560
+ giterr_clear();
561
+ else if (error < 0)
562
+ goto error;
563
+ else {
564
+ error = git_index_open(&index, git_buf_cstr(&index_file_buf));
565
+ if (error < 0)
566
+ goto error;
567
+ }
568
+
569
+ error = git__getenv(&namespace_buf, "GIT_NAMESPACE");
570
+ if (error == GIT_ENOTFOUND)
571
+ giterr_clear();
572
+ else if (error < 0)
573
+ goto error;
574
+
575
+ error = git__getenv(&object_dir_buf, "GIT_OBJECT_DIRECTORY");
576
+ if (error == GIT_ENOTFOUND)
577
+ giterr_clear();
578
+ else if (error < 0)
579
+ goto error;
580
+ else {
581
+ error = git_odb_open(&odb, git_buf_cstr(&object_dir_buf));
582
+ if (error < 0)
583
+ goto error;
584
+ }
585
+
586
+ error = git__getenv(&work_tree_buf, "GIT_WORK_TREE");
587
+ if (error == GIT_ENOTFOUND)
588
+ giterr_clear();
589
+ else if (error < 0)
590
+ goto error;
591
+ else {
592
+ giterr_set(GITERR_INVALID, "GIT_WORK_TREE unimplemented");
593
+ error = GIT_ERROR;
594
+ goto error;
595
+ }
596
+
597
+ error = git__getenv(&work_tree_buf, "GIT_COMMON_DIR");
598
+ if (error == GIT_ENOTFOUND)
599
+ giterr_clear();
600
+ else if (error < 0)
601
+ goto error;
602
+ else {
603
+ giterr_set(GITERR_INVALID, "GIT_COMMON_DIR unimplemented");
604
+ error = GIT_ERROR;
605
+ goto error;
606
+ }
607
+
608
+ error = git_repository_open_ext(&repo, start_path, flags, ceiling_dirs);
609
+ if (error < 0)
610
+ goto error;
611
+
612
+ if (odb)
613
+ git_repository_set_odb(repo, odb);
614
+
615
+ error = git__getenv(&alts_buf, "GIT_ALTERNATE_OBJECT_DIRECTORIES");
616
+ if (error == GIT_ENOTFOUND)
617
+ giterr_clear();
618
+ else if (error < 0)
619
+ goto error;
620
+ else {
621
+ const char *end;
622
+ char *alt, *sep;
623
+ if (!odb) {
624
+ error = git_repository_odb(&odb, repo);
625
+ if (error < 0)
626
+ goto error;
627
+ }
628
+
629
+ end = git_buf_cstr(&alts_buf) + git_buf_len(&alts_buf);
630
+ for (sep = alt = alts_buf.ptr; sep != end; alt = sep+1) {
631
+ for (sep = alt; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++)
632
+ ;
633
+ if (*sep)
634
+ *sep = '\0';
635
+ error = git_odb_add_disk_alternate(odb, alt);
636
+ if (error < 0)
637
+ goto error;
638
+ }
639
+ }
640
+
641
+ error = git_repository_set_namespace(repo, git_buf_cstr(&namespace_buf));
642
+ if (error < 0)
643
+ goto error;
644
+
645
+ git_repository_set_index(repo, index);
646
+
647
+ if (out) {
648
+ *out = repo;
649
+ goto success;
650
+ }
651
+ error:
652
+ git_repository_free(repo);
653
+ success:
654
+ git_odb_free(odb);
655
+ git_index_free(index);
656
+ git_buf_free(&common_dir_buf);
657
+ git_buf_free(&work_tree_buf);
658
+ git_buf_free(&alts_buf);
659
+ git_buf_free(&object_dir_buf);
660
+ git_buf_free(&namespace_buf);
661
+ git_buf_free(&index_file_buf);
662
+ git_buf_free(&across_fs_buf);
663
+ git_buf_free(&ceiling_dirs_buf);
664
+ git_buf_free(&dir_buf);
665
+ return error;
666
+ }
667
+
483
668
  int git_repository_open_ext(
484
669
  git_repository **repo_ptr,
485
670
  const char *start_path,
@@ -492,6 +677,9 @@ int git_repository_open_ext(
492
677
  git_repository *repo;
493
678
  git_config *config = NULL;
494
679
 
680
+ if (flags & GIT_REPOSITORY_OPEN_FROM_ENV)
681
+ return _git_repository_open_ext_from_env(repo_ptr, start_path);
682
+
495
683
  if (repo_ptr)
496
684
  *repo_ptr = NULL;
497
685