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
@@ -50,14 +50,11 @@ GIT_INLINE(git_filemode_t) normalize_filemode(git_filemode_t filemode)
50
50
  return GIT_FILEMODE_BLOB;
51
51
  }
52
52
 
53
- static int valid_entry_name(const char *filename)
53
+ static int valid_entry_name(git_repository *repo, const char *filename)
54
54
  {
55
55
  return *filename != '\0' &&
56
- strchr(filename, '/') == NULL &&
57
- (*filename != '.' ||
58
- (strcmp(filename, ".") != 0 &&
59
- strcmp(filename, "..") != 0 &&
60
- strcmp(filename, DOT_GIT) != 0));
56
+ git_path_isvalid(repo, filename,
57
+ GIT_PATH_REJECT_TRAVERSAL | GIT_PATH_REJECT_DOT_GIT | GIT_PATH_REJECT_SLASH);
61
58
  }
62
59
 
63
60
  static int entry_sort_cmp(const void *a, const void *b)
@@ -455,7 +452,7 @@ static int append_entry(
455
452
  git_tree_entry *entry;
456
453
  int error = 0;
457
454
 
458
- if (!valid_entry_name(filename))
455
+ if (!valid_entry_name(bld->repo, filename))
459
456
  return tree_error("Failed to insert entry. Invalid name for a tree entry", filename);
460
457
 
461
458
  entry = alloc_entry(filename);
@@ -493,7 +490,7 @@ static int write_tree(
493
490
  return (int)find_next_dir(dirname, index, start);
494
491
  }
495
492
 
496
- if ((error = git_treebuilder_create(&bld, NULL)) < 0 || bld == NULL)
493
+ if ((error = git_treebuilder_create(&bld, repo, NULL)) < 0 || bld == NULL)
497
494
  return -1;
498
495
 
499
496
  /*
@@ -564,7 +561,7 @@ static int write_tree(
564
561
  }
565
562
  }
566
563
 
567
- if (git_treebuilder_write(oid, repo, bld) < 0)
564
+ if (git_treebuilder_write(oid, bld) < 0)
568
565
  goto on_error;
569
566
 
570
567
  git_treebuilder_free(bld);
@@ -627,16 +624,21 @@ int git_tree__write_index(
627
624
  return ret;
628
625
  }
629
626
 
630
- int git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source)
627
+ int git_treebuilder_create(
628
+ git_treebuilder **builder_p,
629
+ git_repository *repo,
630
+ const git_tree *source)
631
631
  {
632
632
  git_treebuilder *bld;
633
633
  size_t i;
634
634
 
635
- assert(builder_p);
635
+ assert(builder_p && repo);
636
636
 
637
637
  bld = git__calloc(1, sizeof(git_treebuilder));
638
638
  GITERR_CHECK_ALLOC(bld);
639
639
 
640
+ bld->repo = repo;
641
+
640
642
  if (git_strmap_alloc(&bld->map) < 0) {
641
643
  git__free(bld);
642
644
  return -1;
@@ -678,7 +680,7 @@ int git_treebuilder_insert(
678
680
  if (!valid_filemode(filemode))
679
681
  return tree_error("Failed to insert entry. Invalid filemode for file", filename);
680
682
 
681
- if (!valid_entry_name(filename))
683
+ if (!valid_entry_name(bld->repo, filename))
682
684
  return tree_error("Failed to insert entry. Invalid name for a tree entry", filename);
683
685
 
684
686
  pos = git_strmap_lookup_index(bld->map, filename);
@@ -738,7 +740,7 @@ int git_treebuilder_remove(git_treebuilder *bld, const char *filename)
738
740
  return 0;
739
741
  }
740
742
 
741
- int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *bld)
743
+ int git_treebuilder_write(git_oid *oid, git_treebuilder *bld)
742
744
  {
743
745
  int error = 0;
744
746
  size_t i, entrycount;
@@ -777,7 +779,7 @@ int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *b
777
779
  git_vector_free(&entries);
778
780
 
779
781
  if (!error &&
780
- !(error = git_repository_odb__weakptr(&odb, repo)))
782
+ !(error = git_repository_odb__weakptr(&odb, bld->repo)))
781
783
  error = git_odb_write(oid, odb, tree.ptr, tree.size, GIT_OBJ_TREE);
782
784
 
783
785
  git_buf_free(&tree);
@@ -26,6 +26,7 @@ struct git_tree {
26
26
  };
27
27
 
28
28
  struct git_treebuilder {
29
+ git_repository *repo;
29
30
  git_strmap *map;
30
31
  };
31
32
 
@@ -250,6 +250,21 @@ int git__prefixcmp_icase(const char *str, const char *prefix)
250
250
  return strncasecmp(str, prefix, strlen(prefix));
251
251
  }
252
252
 
253
+ int git__prefixncmp_icase(const char *str, size_t str_n, const char *prefix)
254
+ {
255
+ int s, p;
256
+
257
+ while(str_n--) {
258
+ s = (unsigned char)tolower(*str++);
259
+ p = (unsigned char)tolower(*prefix++);
260
+
261
+ if (s != p)
262
+ return s - p;
263
+ }
264
+
265
+ return (0 - *prefix);
266
+ }
267
+
253
268
  int git__suffixcmp(const char *str, const char *suffix)
254
269
  {
255
270
  size_t a = strlen(str);
@@ -649,3 +664,79 @@ void git__insertsort_r(
649
664
  if (freeswap)
650
665
  git__free(swapel);
651
666
  }
667
+
668
+ static const int8_t utf8proc_utf8class[256] = {
669
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
670
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
671
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
672
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
673
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
674
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
675
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
676
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
677
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
678
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
679
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
680
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
681
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
682
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
683
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
684
+ 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0
685
+ };
686
+
687
+ int git__utf8_charlen(const uint8_t *str, int str_len)
688
+ {
689
+ int length, i;
690
+
691
+ length = utf8proc_utf8class[str[0]];
692
+ if (!length)
693
+ return -1;
694
+
695
+ if (str_len >= 0 && length > str_len)
696
+ return -str_len;
697
+
698
+ for (i = 1; i < length; i++) {
699
+ if ((str[i] & 0xC0) != 0x80)
700
+ return -i;
701
+ }
702
+
703
+ return length;
704
+ }
705
+
706
+ int git__utf8_iterate(const uint8_t *str, int str_len, int32_t *dst)
707
+ {
708
+ int length;
709
+ int32_t uc = -1;
710
+
711
+ *dst = -1;
712
+ length = git__utf8_charlen(str, str_len);
713
+ if (length < 0)
714
+ return -1;
715
+
716
+ switch (length) {
717
+ case 1:
718
+ uc = str[0];
719
+ break;
720
+ case 2:
721
+ uc = ((str[0] & 0x1F) << 6) + (str[1] & 0x3F);
722
+ if (uc < 0x80) uc = -1;
723
+ break;
724
+ case 3:
725
+ uc = ((str[0] & 0x0F) << 12) + ((str[1] & 0x3F) << 6)
726
+ + (str[2] & 0x3F);
727
+ if (uc < 0x800 || (uc >= 0xD800 && uc < 0xE000) ||
728
+ (uc >= 0xFDD0 && uc < 0xFDF0)) uc = -1;
729
+ break;
730
+ case 4:
731
+ uc = ((str[0] & 0x07) << 18) + ((str[1] & 0x3F) << 12)
732
+ + ((str[2] & 0x3F) << 6) + (str[3] & 0x3F);
733
+ if (uc < 0x10000 || uc >= 0x110000) uc = -1;
734
+ break;
735
+ }
736
+
737
+ if (uc < 0 || ((uc & 0xFFFF) >= 0xFFFE))
738
+ return -1;
739
+
740
+ *dst = uc;
741
+ return length;
742
+ }
@@ -106,6 +106,7 @@ GIT_INLINE(void) git__free(void *ptr)
106
106
 
107
107
  extern int git__prefixcmp(const char *str, const char *prefix);
108
108
  extern int git__prefixcmp_icase(const char *str, const char *prefix);
109
+ extern int git__prefixncmp_icase(const char *str, size_t str_n, const char *prefix);
109
110
  extern int git__suffixcmp(const char *str, const char *suffix);
110
111
 
111
112
  GIT_INLINE(int) git__signum(int val)
@@ -366,6 +367,17 @@ extern int git__date_rfc2822_fmt(char *out, size_t len, const git_time *date);
366
367
  */
367
368
  extern size_t git__unescape(char *str);
368
369
 
370
+ /*
371
+ * Iterate through an UTF-8 string, yielding one
372
+ * codepoint at a time.
373
+ *
374
+ * @param str current position in the string
375
+ * @param str_len size left in the string; -1 if the string is NULL-terminated
376
+ * @param dst pointer where to store the current codepoint
377
+ * @return length in bytes of the read codepoint; -1 if the codepoint was invalid
378
+ */
379
+ extern int git__utf8_iterate(const uint8_t *str, int str_len, int32_t *dst);
380
+
369
381
  /*
370
382
  * Safely zero-out memory, making sure that the compiler
371
383
  * doesn't optimize away the operation.
@@ -5,6 +5,7 @@
5
5
  * a Linking Exception. For full terms see the included COPYING file.
6
6
  */
7
7
 
8
+ #include "path_w32.h"
8
9
  #include "utf-conv.h"
9
10
  #include "path.h"
10
11
  #include "findfile.h"
@@ -0,0 +1,305 @@
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
+
8
+ #include "common.h"
9
+ #include "path.h"
10
+ #include "path_w32.h"
11
+ #include "utf-conv.h"
12
+
13
+ #define PATH__NT_NAMESPACE L"\\\\?\\"
14
+ #define PATH__NT_NAMESPACE_LEN 4
15
+
16
+ #define PATH__ABSOLUTE_LEN 3
17
+
18
+ #define path__is_dirsep(p) ((p) == '/' || (p) == '\\')
19
+
20
+ #define path__is_absolute(p) \
21
+ (git__isalpha((p)[0]) && (p)[1] == ':' && ((p)[2] == '\\' || (p)[2] == '/'))
22
+
23
+ #define path__is_nt_namespace(p) \
24
+ (((p)[0] == '\\' && (p)[1] == '\\' && (p)[2] == '?' && (p)[3] == '\\') || \
25
+ ((p)[0] == '/' && (p)[1] == '/' && (p)[2] == '?' && (p)[3] == '/'))
26
+
27
+ #define path__is_unc(p) \
28
+ (((p)[0] == '\\' && (p)[1] == '\\') || ((p)[0] == '/' && (p)[1] == '/'))
29
+
30
+ GIT_INLINE(int) path__cwd(wchar_t *path, int size)
31
+ {
32
+ int len;
33
+
34
+ if ((len = GetCurrentDirectoryW(size, path)) == 0) {
35
+ errno = GetLastError() == ERROR_ACCESS_DENIED ? EACCES : ENOENT;
36
+ return -1;
37
+ } else if (len > size) {
38
+ errno = ENAMETOOLONG;
39
+ return -1;
40
+ }
41
+
42
+ /* The Win32 APIs may return "\\?\" once you've used it first.
43
+ * But it may not. What a gloriously predictible API!
44
+ */
45
+ if (wcsncmp(path, PATH__NT_NAMESPACE, PATH__NT_NAMESPACE_LEN))
46
+ return len;
47
+
48
+ len -= PATH__NT_NAMESPACE_LEN;
49
+
50
+ memmove(path, path + PATH__NT_NAMESPACE_LEN, sizeof(wchar_t) * len);
51
+ return len;
52
+ }
53
+
54
+ static wchar_t *path__skip_server(wchar_t *path)
55
+ {
56
+ wchar_t *c;
57
+
58
+ for (c = path; *c; c++) {
59
+ if (path__is_dirsep(*c))
60
+ return c + 1;
61
+ }
62
+
63
+ return c;
64
+ }
65
+
66
+ static wchar_t *path__skip_prefix(wchar_t *path)
67
+ {
68
+ if (path__is_nt_namespace(path)) {
69
+ path += PATH__NT_NAMESPACE_LEN;
70
+
71
+ if (wcsncmp(path, L"UNC\\", 4) == 0)
72
+ path = path__skip_server(path + 4);
73
+ else if (path__is_absolute(path))
74
+ path += PATH__ABSOLUTE_LEN;
75
+ } else if (path__is_absolute(path)) {
76
+ path += PATH__ABSOLUTE_LEN;
77
+ } else if (path__is_unc(path)) {
78
+ path = path__skip_server(path + 2);
79
+ }
80
+
81
+ return path;
82
+ }
83
+
84
+ int git_win32_path_canonicalize(git_win32_path path)
85
+ {
86
+ wchar_t *base, *from, *to, *next;
87
+ size_t len;
88
+
89
+ base = to = path__skip_prefix(path);
90
+
91
+ /* Unposixify if the prefix */
92
+ for (from = path; from < to; from++) {
93
+ if (*from == L'/')
94
+ *from = L'\\';
95
+ }
96
+
97
+ while (*from) {
98
+ for (next = from; *next; ++next) {
99
+ if (*next == L'/') {
100
+ *next = L'\\';
101
+ break;
102
+ }
103
+
104
+ if (*next == L'\\')
105
+ break;
106
+ }
107
+
108
+ len = next - from;
109
+
110
+ if (len == 1 && from[0] == L'.')
111
+ /* do nothing with singleton dot */;
112
+
113
+ else if (len == 2 && from[0] == L'.' && from[1] == L'.') {
114
+ if (to == base) {
115
+ /* no more path segments to strip, eat the "../" */
116
+ if (*next == L'\\')
117
+ len++;
118
+
119
+ base = to;
120
+ } else {
121
+ /* back up a path segment */
122
+ while (to > base && to[-1] == L'\\') to--;
123
+ while (to > base && to[-1] != L'\\') to--;
124
+ }
125
+ } else {
126
+ if (*next == L'\\' && *from != L'\\')
127
+ len++;
128
+
129
+ if (to != from)
130
+ memmove(to, from, sizeof(wchar_t) * len);
131
+
132
+ to += len;
133
+ }
134
+
135
+ from += len;
136
+
137
+ while (*from == L'\\') from++;
138
+ }
139
+
140
+ /* Strip trailing backslashes */
141
+ while (to > base && to[-1] == L'\\') to--;
142
+
143
+ *to = L'\0';
144
+
145
+ return (to - path);
146
+ }
147
+
148
+ int git_win32_path__cwd(wchar_t *out, size_t len)
149
+ {
150
+ int cwd_len;
151
+
152
+ if ((cwd_len = path__cwd(out, len)) < 0)
153
+ return -1;
154
+
155
+ /* UNC paths */
156
+ if (wcsncmp(L"\\\\", out, 2) == 0) {
157
+ /* Our buffer must be at least 5 characters larger than the
158
+ * current working directory: we swallow one of the leading
159
+ * '\'s, but we we add a 'UNC' specifier to the path, plus
160
+ * a trailing directory separator, plus a NUL.
161
+ */
162
+ if (cwd_len > MAX_PATH - 4) {
163
+ errno = ENAMETOOLONG;
164
+ return -1;
165
+ }
166
+
167
+ memmove(out+2, out, sizeof(wchar_t) * cwd_len);
168
+ out[0] = L'U';
169
+ out[1] = L'N';
170
+ out[2] = L'C';
171
+
172
+ cwd_len += 2;
173
+ }
174
+
175
+ /* Our buffer must be at least 2 characters larger than the current
176
+ * working directory. (One character for the directory separator,
177
+ * one for the null.
178
+ */
179
+ else if (cwd_len > MAX_PATH - 2) {
180
+ errno = ENAMETOOLONG;
181
+ return -1;
182
+ }
183
+
184
+ return cwd_len;
185
+ }
186
+
187
+ int git_win32_path_from_utf8(git_win32_path out, const char *src)
188
+ {
189
+ wchar_t *dest = out;
190
+
191
+ /* All win32 paths are in NT-prefixed format, beginning with "\\?\". */
192
+ memcpy(dest, PATH__NT_NAMESPACE, sizeof(wchar_t) * PATH__NT_NAMESPACE_LEN);
193
+ dest += PATH__NT_NAMESPACE_LEN;
194
+
195
+ /* See if this is an absolute path (beginning with a drive letter) */
196
+ if (path__is_absolute(src)) {
197
+ if (git__utf8_to_16(dest, MAX_PATH, src) < 0)
198
+ return -1;
199
+ }
200
+ /* File-prefixed NT-style paths beginning with \\?\ */
201
+ else if (path__is_nt_namespace(src)) {
202
+ /* Skip the NT prefix, the destination already contains it */
203
+ if (git__utf8_to_16(dest, MAX_PATH, src + PATH__NT_NAMESPACE_LEN) < 0)
204
+ return -1;
205
+ }
206
+ /* UNC paths */
207
+ else if (path__is_unc(src)) {
208
+ memcpy(dest, L"UNC\\", sizeof(wchar_t) * 4);
209
+ dest += 4;
210
+
211
+ /* Skip the leading "\\" */
212
+ if (git__utf8_to_16(dest, MAX_PATH - 2, src + 2) < 0)
213
+ return -1;
214
+ }
215
+ /* Absolute paths omitting the drive letter */
216
+ else if (src[0] == '\\' || src[0] == '/') {
217
+ if (path__cwd(dest, MAX_PATH) < 0)
218
+ return -1;
219
+
220
+ if (!path__is_absolute(dest)) {
221
+ errno = ENOENT;
222
+ return -1;
223
+ }
224
+
225
+ /* Skip the drive letter specification ("C:") */
226
+ if (git__utf8_to_16(dest + 2, MAX_PATH - 2, src) < 0)
227
+ return -1;
228
+ }
229
+ /* Relative paths */
230
+ else {
231
+ int cwd_len;
232
+
233
+ if ((cwd_len = git_win32_path__cwd(dest, MAX_PATH)) < 0)
234
+ return -1;
235
+
236
+ dest[cwd_len++] = L'\\';
237
+
238
+ if (git__utf8_to_16(dest + cwd_len, MAX_PATH - cwd_len, src) < 0)
239
+ return -1;
240
+ }
241
+
242
+ return git_win32_path_canonicalize(out);
243
+ }
244
+
245
+ int git_win32_path_to_utf8(git_win32_utf8_path dest, const wchar_t *src)
246
+ {
247
+ char *out = dest;
248
+ int len;
249
+
250
+ /* Strip NT namespacing "\\?\" */
251
+ if (path__is_nt_namespace(src)) {
252
+ src += 4;
253
+
254
+ /* "\\?\UNC\server\share" -> "\\server\share" */
255
+ if (wcsncmp(src, L"UNC\\", 4) == 0) {
256
+ src += 4;
257
+
258
+ memcpy(dest, "\\\\", 2);
259
+ out = dest + 2;
260
+ }
261
+ }
262
+
263
+ if ((len = git__utf16_to_8(out, GIT_WIN_PATH_UTF8, src)) < 0)
264
+ return len;
265
+
266
+ git_path_mkposix(dest);
267
+
268
+ return len;
269
+ }
270
+
271
+ char *git_win32_path_8dot3_name(const char *path)
272
+ {
273
+ git_win32_path longpath, shortpath;
274
+ wchar_t *start;
275
+ char *shortname;
276
+ int len, namelen = 1;
277
+
278
+ if (git_win32_path_from_utf8(longpath, path) < 0)
279
+ return NULL;
280
+
281
+ len = GetShortPathNameW(longpath, shortpath, GIT_WIN_PATH_UTF16);
282
+
283
+ while (len && shortpath[len-1] == L'\\')
284
+ shortpath[--len] = L'\0';
285
+
286
+ if (len == 0 || len >= GIT_WIN_PATH_UTF16)
287
+ return NULL;
288
+
289
+ for (start = shortpath + (len - 1);
290
+ start > shortpath && *(start-1) != '/' && *(start-1) != '\\';
291
+ start--)
292
+ namelen++;
293
+
294
+ /* We may not have actually been given a short name. But if we have,
295
+ * it will be in the ASCII byte range, so we don't need to worry about
296
+ * multi-byte sequences and can allocate naively.
297
+ */
298
+ if (namelen > 12 || (shortname = git__malloc(namelen + 1)) == NULL)
299
+ return NULL;
300
+
301
+ if ((len = git__utf16_to_8(shortname, namelen + 1, start)) < 0)
302
+ return NULL;
303
+
304
+ return shortname;
305
+ }