rugged 0.22.0b4 → 0.22.0b5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/rugged.c +8 -7
  3. data/ext/rugged/rugged_note.c +1 -1
  4. data/ext/rugged/rugged_remote.c +0 -5
  5. data/ext/rugged/rugged_tree.c +23 -25
  6. data/lib/rugged/version.rb +1 -1
  7. data/vendor/libgit2/include/git2/blame.h +0 -1
  8. data/vendor/libgit2/include/git2/branch.h +1 -1
  9. data/vendor/libgit2/include/git2/buffer.h +1 -1
  10. data/vendor/libgit2/include/git2/cherrypick.h +5 -2
  11. data/vendor/libgit2/include/git2/clone.h +0 -1
  12. data/vendor/libgit2/include/git2/common.h +6 -1
  13. data/vendor/libgit2/include/git2/config.h +13 -4
  14. data/vendor/libgit2/include/git2/filter.h +3 -0
  15. data/vendor/libgit2/include/git2/global.h +10 -4
  16. data/vendor/libgit2/include/git2/index.h +3 -0
  17. data/vendor/libgit2/include/git2/merge.h +20 -5
  18. data/vendor/libgit2/include/git2/net.h +3 -2
  19. data/vendor/libgit2/include/git2/notes.h +5 -7
  20. data/vendor/libgit2/include/git2/push.h +7 -14
  21. data/vendor/libgit2/include/git2/rebase.h +14 -1
  22. data/vendor/libgit2/include/git2/refs.h +7 -1
  23. data/vendor/libgit2/include/git2/remote.h +6 -1
  24. data/vendor/libgit2/include/git2/repository.h +6 -0
  25. data/vendor/libgit2/include/git2/revert.h +5 -2
  26. data/vendor/libgit2/include/git2/stash.h +15 -6
  27. data/vendor/libgit2/include/git2/submodule.h +1 -1
  28. data/vendor/libgit2/include/git2/sys/diff.h +5 -2
  29. data/vendor/libgit2/include/git2/sys/hashsig.h +3 -0
  30. data/vendor/libgit2/include/git2/sys/mempack.h +1 -1
  31. data/vendor/libgit2/include/git2/sys/stream.h +40 -0
  32. data/vendor/libgit2/include/git2/sys/transport.h +17 -4
  33. data/vendor/libgit2/include/git2/tree.h +3 -3
  34. data/vendor/libgit2/src/checkout.c +27 -1
  35. data/vendor/libgit2/src/commit_list.c +1 -1
  36. data/vendor/libgit2/src/common.h +1 -1
  37. data/vendor/libgit2/src/config_cache.c +2 -0
  38. data/vendor/libgit2/src/config_file.c +1 -1
  39. data/vendor/libgit2/src/describe.c +2 -2
  40. data/vendor/libgit2/src/global.c +31 -14
  41. data/vendor/libgit2/src/ignore.c +86 -3
  42. data/vendor/libgit2/src/index.c +48 -25
  43. data/vendor/libgit2/src/indexer.c +1 -0
  44. data/vendor/libgit2/src/netops.c +18 -474
  45. data/vendor/libgit2/src/netops.h +3 -8
  46. data/vendor/libgit2/src/notes.c +3 -3
  47. data/vendor/libgit2/src/odb.c +1 -0
  48. data/vendor/libgit2/src/odb_loose.c +1 -1
  49. data/vendor/libgit2/src/openssl_stream.c +375 -0
  50. data/vendor/libgit2/src/openssl_stream.h +14 -0
  51. data/vendor/libgit2/src/path.c +256 -0
  52. data/vendor/libgit2/src/path.h +44 -1
  53. data/vendor/libgit2/src/pool.c +1 -1
  54. data/vendor/libgit2/src/push.c +5 -5
  55. data/vendor/libgit2/src/rebase.c +2 -2
  56. data/vendor/libgit2/src/refdb_fs.c +11 -1
  57. data/vendor/libgit2/src/remote.c +2 -7
  58. data/vendor/libgit2/src/repository.c +25 -0
  59. data/vendor/libgit2/src/repository.h +26 -2
  60. data/vendor/libgit2/src/socket_stream.c +212 -0
  61. data/vendor/libgit2/src/socket_stream.h +21 -0
  62. data/vendor/libgit2/src/stream.h +48 -0
  63. data/vendor/libgit2/src/tag.c +1 -1
  64. data/vendor/libgit2/src/transports/git.c +71 -57
  65. data/vendor/libgit2/src/transports/http.c +40 -62
  66. data/vendor/libgit2/src/transports/local.c +6 -11
  67. data/vendor/libgit2/src/transports/smart.c +3 -3
  68. data/vendor/libgit2/src/transports/ssh.c +12 -8
  69. data/vendor/libgit2/src/transports/winhttp.c +68 -47
  70. data/vendor/libgit2/src/tree.c +16 -14
  71. data/vendor/libgit2/src/tree.h +1 -0
  72. data/vendor/libgit2/src/util.c +91 -0
  73. data/vendor/libgit2/src/util.h +12 -0
  74. data/vendor/libgit2/src/win32/findfile.c +1 -0
  75. data/vendor/libgit2/src/win32/path_w32.c +305 -0
  76. data/vendor/libgit2/src/win32/path_w32.h +80 -0
  77. data/vendor/libgit2/src/win32/posix.h +1 -0
  78. data/vendor/libgit2/src/win32/posix_w32.c +25 -42
  79. data/vendor/libgit2/src/win32/utf-conv.c +36 -6
  80. data/vendor/libgit2/src/win32/utf-conv.h +0 -39
  81. data/vendor/libgit2/src/win32/w32_util.h +1 -0
  82. data/vendor/libgit2/src/xdiff/xdiffi.c +1 -1
  83. data/vendor/libgit2/src/xdiff/xhistogram.c +1 -1
  84. metadata +10 -2
@@ -0,0 +1,14 @@
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_openssl_stream_h__
8
+ #define INCLUDE_openssl_stream_h__
9
+
10
+ #include "git2/sys/stream.h"
11
+
12
+ extern int git_openssl_stream_new(git_stream **out, const char *host, const char *port);
13
+
14
+ #endif
@@ -7,6 +7,7 @@
7
7
  #include "common.h"
8
8
  #include "path.h"
9
9
  #include "posix.h"
10
+ #include "repository.h"
10
11
  #ifdef GIT_WIN32
11
12
  #include "win32/posix.h"
12
13
  #include "win32/w32_util.h"
@@ -1238,3 +1239,258 @@ int git_path_from_url_or_path(git_buf *local_path_out, const char *url_or_path)
1238
1239
  else
1239
1240
  return git_buf_sets(local_path_out, url_or_path);
1240
1241
  }
1242
+
1243
+ /* Reject paths like AUX or COM1, or those versions that end in a dot or
1244
+ * colon. ("AUX." or "AUX:")
1245
+ */
1246
+ GIT_INLINE(bool) verify_dospath(
1247
+ const char *component,
1248
+ size_t len,
1249
+ const char dospath[3],
1250
+ bool trailing_num)
1251
+ {
1252
+ size_t last = trailing_num ? 4 : 3;
1253
+
1254
+ if (len < last || git__strncasecmp(component, dospath, 3) != 0)
1255
+ return true;
1256
+
1257
+ if (trailing_num && !git__isdigit(component[3]))
1258
+ return true;
1259
+
1260
+ return (len > last &&
1261
+ component[last] != '.' &&
1262
+ component[last] != ':');
1263
+ }
1264
+
1265
+ static int32_t next_hfs_char(const char **in, size_t *len)
1266
+ {
1267
+ while (*len) {
1268
+ int32_t codepoint;
1269
+ int cp_len = git__utf8_iterate((const uint8_t *)(*in), (int)(*len), &codepoint);
1270
+ if (cp_len < 0)
1271
+ return -1;
1272
+
1273
+ (*in) += cp_len;
1274
+ (*len) -= cp_len;
1275
+
1276
+ /* these code points are ignored completely */
1277
+ switch (codepoint) {
1278
+ case 0x200c: /* ZERO WIDTH NON-JOINER */
1279
+ case 0x200d: /* ZERO WIDTH JOINER */
1280
+ case 0x200e: /* LEFT-TO-RIGHT MARK */
1281
+ case 0x200f: /* RIGHT-TO-LEFT MARK */
1282
+ case 0x202a: /* LEFT-TO-RIGHT EMBEDDING */
1283
+ case 0x202b: /* RIGHT-TO-LEFT EMBEDDING */
1284
+ case 0x202c: /* POP DIRECTIONAL FORMATTING */
1285
+ case 0x202d: /* LEFT-TO-RIGHT OVERRIDE */
1286
+ case 0x202e: /* RIGHT-TO-LEFT OVERRIDE */
1287
+ case 0x206a: /* INHIBIT SYMMETRIC SWAPPING */
1288
+ case 0x206b: /* ACTIVATE SYMMETRIC SWAPPING */
1289
+ case 0x206c: /* INHIBIT ARABIC FORM SHAPING */
1290
+ case 0x206d: /* ACTIVATE ARABIC FORM SHAPING */
1291
+ case 0x206e: /* NATIONAL DIGIT SHAPES */
1292
+ case 0x206f: /* NOMINAL DIGIT SHAPES */
1293
+ case 0xfeff: /* ZERO WIDTH NO-BREAK SPACE */
1294
+ continue;
1295
+ }
1296
+
1297
+ /* fold into lowercase -- this will only fold characters in
1298
+ * the ASCII range, which is perfectly fine, because the
1299
+ * git folder name can only be composed of ascii characters
1300
+ */
1301
+ return tolower(codepoint);
1302
+ }
1303
+ return 0; /* NULL byte -- end of string */
1304
+ }
1305
+
1306
+ static bool verify_dotgit_hfs(const char *path, size_t len)
1307
+ {
1308
+ if (next_hfs_char(&path, &len) != '.' ||
1309
+ next_hfs_char(&path, &len) != 'g' ||
1310
+ next_hfs_char(&path, &len) != 'i' ||
1311
+ next_hfs_char(&path, &len) != 't' ||
1312
+ next_hfs_char(&path, &len) != 0)
1313
+ return true;
1314
+
1315
+ return false;
1316
+ }
1317
+
1318
+ GIT_INLINE(bool) verify_dotgit_ntfs(git_repository *repo, const char *path, size_t len)
1319
+ {
1320
+ const char *shortname = NULL;
1321
+ size_t i, start, shortname_len = 0;
1322
+
1323
+ /* See if the repo has a custom shortname (not "GIT~1") */
1324
+ if (repo &&
1325
+ (shortname = git_repository__8dot3_name(repo)) &&
1326
+ shortname != git_repository__8dot3_default)
1327
+ shortname_len = strlen(shortname);
1328
+
1329
+ if (len >= 4 && strncasecmp(path, ".git", 4) == 0)
1330
+ start = 4;
1331
+ else if (len >= git_repository__8dot3_default_len &&
1332
+ strncasecmp(path, git_repository__8dot3_default, git_repository__8dot3_default_len) == 0)
1333
+ start = git_repository__8dot3_default_len;
1334
+ else if (shortname_len && len >= shortname_len &&
1335
+ strncasecmp(path, shortname, shortname_len) == 0)
1336
+ start = shortname_len;
1337
+ else
1338
+ return true;
1339
+
1340
+ /* Reject paths beginning with ".git\" */
1341
+ if (path[start] == '\\')
1342
+ return false;
1343
+
1344
+ for (i = start; i < len; i++) {
1345
+ if (path[i] != ' ' && path[i] != '.')
1346
+ return true;
1347
+ }
1348
+
1349
+ return false;
1350
+ }
1351
+
1352
+ GIT_INLINE(bool) verify_char(unsigned char c, unsigned int flags)
1353
+ {
1354
+ if ((flags & GIT_PATH_REJECT_BACKSLASH) && c == '\\')
1355
+ return false;
1356
+
1357
+ if ((flags & GIT_PATH_REJECT_SLASH) && c == '/')
1358
+ return false;
1359
+
1360
+ if (flags & GIT_PATH_REJECT_NT_CHARS) {
1361
+ if (c < 32)
1362
+ return false;
1363
+
1364
+ switch (c) {
1365
+ case '<':
1366
+ case '>':
1367
+ case ':':
1368
+ case '"':
1369
+ case '|':
1370
+ case '?':
1371
+ case '*':
1372
+ return false;
1373
+ }
1374
+ }
1375
+
1376
+ return true;
1377
+ }
1378
+
1379
+ /*
1380
+ * We fundamentally don't like some paths when dealing with user-inputted
1381
+ * strings (in checkout or ref names): we don't want dot or dot-dot
1382
+ * anywhere, we want to avoid writing weird paths on Windows that can't
1383
+ * be handled by tools that use the non-\\?\ APIs, we don't want slashes
1384
+ * or double slashes at the end of paths that can make them ambiguous.
1385
+ *
1386
+ * For checkout, we don't want to recurse into ".git" either.
1387
+ */
1388
+ static bool verify_component(
1389
+ git_repository *repo,
1390
+ const char *component,
1391
+ size_t len,
1392
+ unsigned int flags)
1393
+ {
1394
+ if (len == 0)
1395
+ return false;
1396
+
1397
+ if ((flags & GIT_PATH_REJECT_TRAVERSAL) &&
1398
+ len == 1 && component[0] == '.')
1399
+ return false;
1400
+
1401
+ if ((flags & GIT_PATH_REJECT_TRAVERSAL) &&
1402
+ len == 2 && component[0] == '.' && component[1] == '.')
1403
+ return false;
1404
+
1405
+ if ((flags & GIT_PATH_REJECT_TRAILING_DOT) && component[len-1] == '.')
1406
+ return false;
1407
+
1408
+ if ((flags & GIT_PATH_REJECT_TRAILING_SPACE) && component[len-1] == ' ')
1409
+ return false;
1410
+
1411
+ if ((flags & GIT_PATH_REJECT_TRAILING_COLON) && component[len-1] == ':')
1412
+ return false;
1413
+
1414
+ if (flags & GIT_PATH_REJECT_DOS_PATHS) {
1415
+ if (!verify_dospath(component, len, "CON", false) ||
1416
+ !verify_dospath(component, len, "PRN", false) ||
1417
+ !verify_dospath(component, len, "AUX", false) ||
1418
+ !verify_dospath(component, len, "NUL", false) ||
1419
+ !verify_dospath(component, len, "COM", true) ||
1420
+ !verify_dospath(component, len, "LPT", true))
1421
+ return false;
1422
+ }
1423
+
1424
+ if (flags & GIT_PATH_REJECT_DOT_GIT_HFS &&
1425
+ !verify_dotgit_hfs(component, len))
1426
+ return false;
1427
+
1428
+ if (flags & GIT_PATH_REJECT_DOT_GIT_NTFS &&
1429
+ !verify_dotgit_ntfs(repo, component, len))
1430
+ return false;
1431
+
1432
+ if ((flags & GIT_PATH_REJECT_DOT_GIT_HFS) == 0 &&
1433
+ (flags & GIT_PATH_REJECT_DOT_GIT_NTFS) == 0 &&
1434
+ (flags & GIT_PATH_REJECT_DOT_GIT) &&
1435
+ len == 4 &&
1436
+ component[0] == '.' &&
1437
+ (component[1] == 'g' || component[1] == 'G') &&
1438
+ (component[2] == 'i' || component[2] == 'I') &&
1439
+ (component[3] == 't' || component[3] == 'T'))
1440
+ return false;
1441
+
1442
+ return true;
1443
+ }
1444
+
1445
+ GIT_INLINE(unsigned int) dotgit_flags(
1446
+ git_repository *repo,
1447
+ unsigned int flags)
1448
+ {
1449
+ int protectHFS = 0, protectNTFS = 0;
1450
+
1451
+ #ifdef __APPLE__
1452
+ protectHFS = 1;
1453
+ #endif
1454
+
1455
+ #ifdef GIT_WIN32
1456
+ protectNTFS = 1;
1457
+ #endif
1458
+
1459
+ if (repo && !protectHFS)
1460
+ git_repository__cvar(&protectHFS, repo, GIT_CVAR_PROTECTHFS);
1461
+ if (protectHFS)
1462
+ flags |= GIT_PATH_REJECT_DOT_GIT_HFS;
1463
+
1464
+ if (repo && !protectNTFS)
1465
+ git_repository__cvar(&protectNTFS, repo, GIT_CVAR_PROTECTNTFS);
1466
+ if (protectNTFS)
1467
+ flags |= GIT_PATH_REJECT_DOT_GIT_NTFS;
1468
+
1469
+ return flags;
1470
+ }
1471
+
1472
+ bool git_path_isvalid(
1473
+ git_repository *repo,
1474
+ const char *path,
1475
+ unsigned int flags)
1476
+ {
1477
+ const char *start, *c;
1478
+
1479
+ /* Upgrade the ".git" checks based on platform */
1480
+ if ((flags & GIT_PATH_REJECT_DOT_GIT))
1481
+ flags = dotgit_flags(repo, flags);
1482
+
1483
+ for (start = c = path; *c; c++) {
1484
+ if (!verify_char(*c, flags))
1485
+ return false;
1486
+
1487
+ if (*c == '/') {
1488
+ if (!verify_component(repo, start, (c - start), flags))
1489
+ return false;
1490
+
1491
+ start = c+1;
1492
+ }
1493
+ }
1494
+
1495
+ return verify_component(repo, start, (c - start), flags);
1496
+ }
@@ -307,7 +307,7 @@ extern int git_path_cmp(
307
307
  * reached (inclusive of a final call at the root_path).
308
308
  *
309
309
  * Returning anything other than 0 from the callback function
310
- * will stop the iteration and propogate the error to the caller.
310
+ * will stop the iteration and propagate the error to the caller.
311
311
  *
312
312
  * @param pathbuf Buffer the function reads the directory from and
313
313
  * and updates with each successive name.
@@ -462,4 +462,47 @@ extern bool git_path_does_fs_decompose_unicode(const char *root);
462
462
  extern bool git_path_is_local_file_url(const char *file_url);
463
463
  extern int git_path_from_url_or_path(git_buf *local_path_out, const char *url_or_path);
464
464
 
465
+ /* Flags to determine path validity in `git_path_isvalid` */
466
+ #define GIT_PATH_REJECT_TRAVERSAL (1 << 0)
467
+ #define GIT_PATH_REJECT_DOT_GIT (1 << 1)
468
+ #define GIT_PATH_REJECT_SLASH (1 << 2)
469
+ #define GIT_PATH_REJECT_BACKSLASH (1 << 3)
470
+ #define GIT_PATH_REJECT_TRAILING_DOT (1 << 4)
471
+ #define GIT_PATH_REJECT_TRAILING_SPACE (1 << 5)
472
+ #define GIT_PATH_REJECT_TRAILING_COLON (1 << 6)
473
+ #define GIT_PATH_REJECT_DOS_PATHS (1 << 7)
474
+ #define GIT_PATH_REJECT_NT_CHARS (1 << 8)
475
+ #define GIT_PATH_REJECT_DOT_GIT_HFS (1 << 9)
476
+ #define GIT_PATH_REJECT_DOT_GIT_NTFS (1 << 10)
477
+
478
+ /* Default path safety for writing files to disk: since we use the
479
+ * Win32 "File Namespace" APIs ("\\?\") we need to protect from
480
+ * paths that the normal Win32 APIs would not write.
481
+ */
482
+ #ifdef GIT_WIN32
483
+ # define GIT_PATH_REJECT_DEFAULTS \
484
+ GIT_PATH_REJECT_TRAVERSAL | \
485
+ GIT_PATH_REJECT_BACKSLASH | \
486
+ GIT_PATH_REJECT_TRAILING_DOT | \
487
+ GIT_PATH_REJECT_TRAILING_SPACE | \
488
+ GIT_PATH_REJECT_TRAILING_COLON | \
489
+ GIT_PATH_REJECT_DOS_PATHS | \
490
+ GIT_PATH_REJECT_NT_CHARS
491
+ #else
492
+ # define GIT_PATH_REJECT_DEFAULTS GIT_PATH_REJECT_TRAVERSAL
493
+ #endif
494
+
495
+ /*
496
+ * Determine whether a path is a valid git path or not - this must not contain
497
+ * a '.' or '..' component, or a component that is ".git" (in any case).
498
+ *
499
+ * `repo` is optional. If specified, it will be used to determine the short
500
+ * path name to reject (if `GIT_PATH_REJECT_DOS_SHORTNAME` is specified),
501
+ * in addition to the default of "git~1".
502
+ */
503
+ extern bool git_path_isvalid(
504
+ git_repository *repo,
505
+ const char *path,
506
+ unsigned int flags);
507
+
465
508
  #endif
@@ -159,7 +159,7 @@ void *git_pool_malloc(git_pool *pool, uint32_t items)
159
159
  return ptr;
160
160
  }
161
161
 
162
- /* just add a block if there is no open one to accomodate this */
162
+ /* just add a block if there is no open one to accommodate this */
163
163
  if (size >= pool->page_size || !scan || scan->avail < size)
164
164
  return pool_alloc_page(pool, size);
165
165
 
@@ -632,12 +632,12 @@ int git_push_finish(git_push *push)
632
632
  (error = do_push(push)) < 0)
633
633
  return error;
634
634
 
635
- return 0;
636
- }
635
+ if (!push->unpack_ok) {
636
+ error = -1;
637
+ giterr_set(GITERR_NET, "unpacking the sent packfile failed on the remote");
638
+ }
637
639
 
638
- int git_push_unpack_ok(const git_push *push)
639
- {
640
- return push->unpack_ok;
640
+ return error;
641
641
  }
642
642
 
643
643
  int git_push_status_foreach(git_push *push,
@@ -972,8 +972,8 @@ static int rebase_copy_note(
972
972
  committer = who;
973
973
  }
974
974
 
975
- error = git_note_create(&note_id, rebase->repo, git_note_author(note),
976
- committer, opts->rewrite_notes_ref, to, git_note_message(note), 0);
975
+ error = git_note_create(&note_id, rebase->repo, opts->rewrite_notes_ref,
976
+ git_note_author(note), committer, to, git_note_message(note), 0);
977
977
 
978
978
  done:
979
979
  git_note_free(note);
@@ -707,11 +707,16 @@ static int reference_path_available(
707
707
 
708
708
  static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *name)
709
709
  {
710
- int error;
710
+ int error;
711
711
  git_buf ref_path = GIT_BUF_INIT;
712
712
 
713
713
  assert(file && backend && name);
714
714
 
715
+ if (!git_path_isvalid(backend->repo, name, GIT_PATH_REJECT_DEFAULTS)) {
716
+ giterr_set(GITERR_INVALID, "Invalid reference name '%s'.", name);
717
+ return GIT_EINVALIDSPEC;
718
+ }
719
+
715
720
  /* Remove a possibly existing empty directory hierarchy
716
721
  * which name would collide with the reference name
717
722
  */
@@ -1653,6 +1658,11 @@ static int lock_reflog(git_filebuf *file, refdb_fs_backend *backend, const char
1653
1658
 
1654
1659
  repo = backend->repo;
1655
1660
 
1661
+ if (!git_path_isvalid(backend->repo, refname, GIT_PATH_REJECT_DEFAULTS)) {
1662
+ giterr_set(GITERR_INVALID, "Invalid reference name '%s'.", refname);
1663
+ return GIT_EINVALIDSPEC;
1664
+ }
1665
+
1656
1666
  if (retrieve_reflog_path(&log_path, repo, refname) < 0)
1657
1667
  return -1;
1658
1668
 
@@ -2160,13 +2160,8 @@ int git_remote_push(git_remote *remote, git_strarray *refspecs, const git_push_o
2160
2160
  if ((error = git_push_finish(push)) < 0)
2161
2161
  goto cleanup;
2162
2162
 
2163
- if (!git_push_unpack_ok(push)) {
2164
- error = -1;
2165
- giterr_set(GITERR_NET, "error in the remote while trying to unpack");
2166
- goto cleanup;
2167
- }
2168
-
2169
- if ((error = git_push_status_foreach(push, cbs->push_update_reference, cbs->payload)) < 0)
2163
+ if (cbs->push_update_reference &&
2164
+ (error = git_push_status_foreach(push, cbs->push_update_reference, cbs->payload)) < 0)
2170
2165
  goto cleanup;
2171
2166
 
2172
2167
  error = git_push_update_tips(push, signature, reflog_message);
@@ -37,6 +37,9 @@
37
37
 
38
38
  #define GIT_REPO_VERSION 0
39
39
 
40
+ const char *git_repository__8dot3_default = "GIT~1";
41
+ size_t git_repository__8dot3_default_len = 5;
42
+
40
43
  static void set_odb(git_repository *repo, git_odb *odb)
41
44
  {
42
45
  if (odb) {
@@ -120,6 +123,7 @@ void git_repository_free(git_repository *repo)
120
123
  git__free(repo->path_repository);
121
124
  git__free(repo->workdir);
122
125
  git__free(repo->namespace);
126
+ git__free(repo->name_8dot3);
123
127
 
124
128
  git__memzero(repo, sizeof(*repo));
125
129
  git__free(repo);
@@ -791,6 +795,27 @@ const char *git_repository_get_namespace(git_repository *repo)
791
795
  return repo->namespace;
792
796
  }
793
797
 
798
+ const char *git_repository__8dot3_name(git_repository *repo)
799
+ {
800
+ if (!repo->has_8dot3) {
801
+ repo->has_8dot3 = 1;
802
+
803
+ #ifdef GIT_WIN32
804
+ if (!repo->is_bare) {
805
+ repo->name_8dot3 = git_win32_path_8dot3_name(repo->path_repository);
806
+
807
+ /* We anticipate the 8.3 name is "GIT~1", so use a static for
808
+ * easy testing in the common case */
809
+ if (strcasecmp(repo->name_8dot3, git_repository__8dot3_default) == 0)
810
+ repo->has_8dot3_default = 1;
811
+ }
812
+ #endif
813
+ }
814
+
815
+ return repo->has_8dot3_default ?
816
+ git_repository__8dot3_default : repo->name_8dot3;
817
+ }
818
+
794
819
  static int check_repositoryformatversion(git_config *config)
795
820
  {
796
821
  int version;