rugged 0.27.0 → 0.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e29dd42f856fd7e0e631d3c3235ebf227fc47490338078fa91e0e4769b16cc64
4
- data.tar.gz: 3f9c8ea45f76799f7eb9096e2de3d551f481f27f5df54cfc21e987a88f9eb019
3
+ metadata.gz: '070298452794464c0fc2d749db1a74ac2575362c59ab6fd6f2ab12a60bb105f7'
4
+ data.tar.gz: ef7f3d39e4cc27ef65226a7cd86dbd89ff05e1bd1c001df09124a202a0a56552
5
5
  SHA512:
6
- metadata.gz: c4e6fefc154bc8e6095cab238a698eb3ccae43e8d07f67192f07dbbe5fbee2f766aa024cec42783c16da914a80abd6c975f928d378a06f378b98a73f2b1abe11
7
- data.tar.gz: e6a565322fd8bb4910168a34791a3793a336012193d5d193a89552d2b806ef946f421e289192a22f3314a1524e2593d80789bfa3d0ec65440b53a1e77afa7192
6
+ metadata.gz: 6c384b5065c2d66e87e0ad43e969fc1e3afc5a02fdec3fe8a4fab3d37c279cc225dee3246aeb38142ca098500006c28362c6082dceda1f75a9f692921b95188f
7
+ data.tar.gz: bf3fff8373c5ce5763374f5ad9133ac8fa754b0787ed44e3b69c2d1e59ff6d379f5e687c20fd0d80178ed366f43bb5337f227c79f4c39511077b84c4764eae78
@@ -4,5 +4,5 @@
4
4
  # For full terms see the included LICENSE file.
5
5
 
6
6
  module Rugged
7
- Version = VERSION = '0.27.0'
7
+ Version = VERSION = '0.27.1'
8
8
  end
@@ -7,10 +7,10 @@
7
7
  #ifndef INCLUDE_git_version_h__
8
8
  #define INCLUDE_git_version_h__
9
9
 
10
- #define LIBGIT2_VERSION "0.27.0"
10
+ #define LIBGIT2_VERSION "0.27.1"
11
11
  #define LIBGIT2_VER_MAJOR 0
12
12
  #define LIBGIT2_VER_MINOR 27
13
- #define LIBGIT2_VER_REVISION 0
13
+ #define LIBGIT2_VER_REVISION 1
14
14
  #define LIBGIT2_VER_PATCH 0
15
15
 
16
16
  #define LIBGIT2_SOVERSION 27
@@ -1276,14 +1276,14 @@ static int checkout_verify_paths(
1276
1276
  unsigned int flags = GIT_PATH_REJECT_WORKDIR_DEFAULTS;
1277
1277
 
1278
1278
  if (action & CHECKOUT_ACTION__REMOVE) {
1279
- if (!git_path_isvalid(repo, delta->old_file.path, flags)) {
1279
+ if (!git_path_isvalid(repo, delta->old_file.path, delta->old_file.mode, flags)) {
1280
1280
  giterr_set(GITERR_CHECKOUT, "cannot remove invalid path '%s'", delta->old_file.path);
1281
1281
  return -1;
1282
1282
  }
1283
1283
  }
1284
1284
 
1285
1285
  if (action & ~CHECKOUT_ACTION__REMOVE) {
1286
- if (!git_path_isvalid(repo, delta->new_file.path, flags)) {
1286
+ if (!git_path_isvalid(repo, delta->new_file.path, delta->new_file.mode, flags)) {
1287
1287
  giterr_set(GITERR_CHECKOUT, "cannot checkout to invalid path '%s'", delta->new_file.path);
1288
1288
  return -1;
1289
1289
  }
@@ -884,11 +884,13 @@ static int index_entry_create(
884
884
  git_index_entry **out,
885
885
  git_repository *repo,
886
886
  const char *path,
887
+ struct stat *st,
887
888
  bool from_workdir)
888
889
  {
889
890
  size_t pathlen = strlen(path), alloclen;
890
891
  struct entry_internal *entry;
891
892
  unsigned int path_valid_flags = GIT_PATH_REJECT_INDEX_DEFAULTS;
893
+ uint16_t mode = 0;
892
894
 
893
895
  /* always reject placing `.git` in the index and directory traversal.
894
896
  * when requested, disallow platform-specific filenames and upgrade to
@@ -896,8 +898,10 @@ static int index_entry_create(
896
898
  */
897
899
  if (from_workdir)
898
900
  path_valid_flags |= GIT_PATH_REJECT_WORKDIR_DEFAULTS;
901
+ if (st)
902
+ mode = st->st_mode;
899
903
 
900
- if (!git_path_isvalid(repo, path, path_valid_flags)) {
904
+ if (!git_path_isvalid(repo, path, mode, path_valid_flags)) {
901
905
  giterr_set(GITERR_INDEX, "invalid path: '%s'", path);
902
906
  return -1;
903
907
  }
@@ -922,15 +926,35 @@ static int index_entry_init(
922
926
  {
923
927
  int error = 0;
924
928
  git_index_entry *entry = NULL;
929
+ git_buf path = GIT_BUF_INIT;
925
930
  struct stat st;
926
931
  git_oid oid;
932
+ git_repository *repo;
927
933
 
928
934
  if (INDEX_OWNER(index) == NULL)
929
935
  return create_index_error(-1,
930
936
  "could not initialize index entry. "
931
937
  "Index is not backed up by an existing repository.");
932
938
 
933
- if (index_entry_create(&entry, INDEX_OWNER(index), rel_path, true) < 0)
939
+ /*
940
+ * FIXME: this is duplicated with the work in
941
+ * git_blob__create_from_paths. It should accept an optional stat
942
+ * structure so we can pass in the one we have to do here.
943
+ */
944
+ repo = INDEX_OWNER(index);
945
+ if (git_repository__ensure_not_bare(repo, "create blob from file") < 0)
946
+ return GIT_EBAREREPO;
947
+
948
+ if (git_buf_joinpath(&path, git_repository_workdir(repo), rel_path) < 0)
949
+ return -1;
950
+
951
+ error = git_path_lstat(path.ptr, &st);
952
+ git_buf_free(&path);
953
+
954
+ if (error < 0)
955
+ return error;
956
+
957
+ if (index_entry_create(&entry, INDEX_OWNER(index), rel_path, &st, true) < 0)
934
958
  return -1;
935
959
 
936
960
  /* write the blob to disk and get the oid and stat info */
@@ -1016,7 +1040,7 @@ static int index_entry_dup(
1016
1040
  git_index *index,
1017
1041
  const git_index_entry *src)
1018
1042
  {
1019
- if (index_entry_create(out, INDEX_OWNER(index), src->path, false) < 0)
1043
+ if (index_entry_create(out, INDEX_OWNER(index), src->path, NULL, false) < 0)
1020
1044
  return -1;
1021
1045
 
1022
1046
  index_entry_cpy(*out, src);
@@ -1038,7 +1062,7 @@ static int index_entry_dup_nocache(
1038
1062
  git_index *index,
1039
1063
  const git_index_entry *src)
1040
1064
  {
1041
- if (index_entry_create(out, INDEX_OWNER(index), src->path, false) < 0)
1065
+ if (index_entry_create(out, INDEX_OWNER(index), src->path, NULL, false) < 0)
1042
1066
  return -1;
1043
1067
 
1044
1068
  index_entry_cpy_nocache(*out, src);
@@ -1461,9 +1485,6 @@ static int add_repo_as_submodule(git_index_entry **out, git_index *index, const
1461
1485
  struct stat st;
1462
1486
  int error;
1463
1487
 
1464
- if (index_entry_create(&entry, INDEX_OWNER(index), path, true) < 0)
1465
- return -1;
1466
-
1467
1488
  if ((error = git_buf_joinpath(&abspath, git_repository_workdir(repo), path)) < 0)
1468
1489
  return error;
1469
1490
 
@@ -1472,6 +1493,9 @@ static int add_repo_as_submodule(git_index_entry **out, git_index *index, const
1472
1493
  return -1;
1473
1494
  }
1474
1495
 
1496
+ if (index_entry_create(&entry, INDEX_OWNER(index), path, &st, true) < 0)
1497
+ return -1;
1498
+
1475
1499
  git_index_entry__init_from_stat(entry, &st, !index->distrust_filemode);
1476
1500
 
1477
1501
  if ((error = git_repository_open(&sub, abspath.ptr)) < 0)
@@ -2965,7 +2989,7 @@ static int read_tree_cb(
2965
2989
  if (git_buf_joinpath(&path, root, tentry->filename) < 0)
2966
2990
  return -1;
2967
2991
 
2968
- if (index_entry_create(&entry, INDEX_OWNER(data->index), path.ptr, false) < 0)
2992
+ if (index_entry_create(&entry, INDEX_OWNER(data->index), path.ptr, NULL, false) < 0)
2969
2993
  return -1;
2970
2994
 
2971
2995
  entry->mode = tentry->attr;
@@ -1561,18 +1561,31 @@ static int32_t next_hfs_char(const char **in, size_t *len)
1561
1561
  return 0; /* NULL byte -- end of string */
1562
1562
  }
1563
1563
 
1564
- static bool verify_dotgit_hfs(const char *path, size_t len)
1564
+ static bool verify_dotgit_hfs_generic(const char *path, size_t len, const char *needle, size_t needle_len)
1565
1565
  {
1566
- if (next_hfs_char(&path, &len) != '.' ||
1567
- next_hfs_char(&path, &len) != 'g' ||
1568
- next_hfs_char(&path, &len) != 'i' ||
1569
- next_hfs_char(&path, &len) != 't' ||
1570
- next_hfs_char(&path, &len) != 0)
1566
+ size_t i;
1567
+ char c;
1568
+
1569
+ if (next_hfs_char(&path, &len) != '.')
1570
+ return true;
1571
+
1572
+ for (i = 0; i < needle_len; i++) {
1573
+ c = next_hfs_char(&path, &len);
1574
+ if (c != needle[i])
1575
+ return true;
1576
+ }
1577
+
1578
+ if (next_hfs_char(&path, &len) != '\0')
1571
1579
  return true;
1572
1580
 
1573
1581
  return false;
1574
1582
  }
1575
1583
 
1584
+ static bool verify_dotgit_hfs(const char *path, size_t len)
1585
+ {
1586
+ return verify_dotgit_hfs_generic(path, len, "git", CONST_STRLEN("git"));
1587
+ }
1588
+
1576
1589
  GIT_INLINE(bool) verify_dotgit_ntfs(git_repository *repo, const char *path, size_t len)
1577
1590
  {
1578
1591
  git_buf *reserved = git_repository__reserved_names_win32;
@@ -1608,6 +1621,57 @@ GIT_INLINE(bool) verify_dotgit_ntfs(git_repository *repo, const char *path, size
1608
1621
  return false;
1609
1622
  }
1610
1623
 
1624
+ GIT_INLINE(bool) only_spaces_and_dots(const char *path)
1625
+ {
1626
+ const char *c = path;
1627
+
1628
+ for (;; c++) {
1629
+ if (*c == '\0')
1630
+ return true;
1631
+ if (*c != ' ' && *c != '.')
1632
+ return false;
1633
+ }
1634
+
1635
+ return true;
1636
+ }
1637
+
1638
+ GIT_INLINE(bool) verify_dotgit_ntfs_generic(const char *name, size_t len, const char *dotgit_name, size_t dotgit_len, const char *shortname_pfix)
1639
+ {
1640
+ int i, saw_tilde;
1641
+
1642
+ if (name[0] == '.' && len >= dotgit_len &&
1643
+ !strncasecmp(name + 1, dotgit_name, dotgit_len)) {
1644
+ return !only_spaces_and_dots(name + dotgit_len + 1);
1645
+ }
1646
+
1647
+ /* Detect the basic NTFS shortname with the first six chars */
1648
+ if (!strncasecmp(name, dotgit_name, 6) && name[6] == '~' &&
1649
+ name[7] >= '1' && name[7] <= '4')
1650
+ return !only_spaces_and_dots(name + 8);
1651
+
1652
+ /* Catch fallback names */
1653
+ for (i = 0, saw_tilde = 0; i < 8; i++) {
1654
+ if (name[i] == '\0') {
1655
+ return true;
1656
+ } else if (saw_tilde) {
1657
+ if (name[i] < '0' || name[i] > '9')
1658
+ return true;
1659
+ } else if (name[i] == '~') {
1660
+ if (name[i+1] < '1' || name[i+1] > '9')
1661
+ return true;
1662
+ saw_tilde = 1;
1663
+ } else if (i >= 6) {
1664
+ return true;
1665
+ } else if (name[i] < 0) {
1666
+ return true;
1667
+ } else if (git__tolower(name[i]) != shortname_pfix[i]) {
1668
+ return true;
1669
+ }
1670
+ }
1671
+
1672
+ return !only_spaces_and_dots(name + i);
1673
+ }
1674
+
1611
1675
  GIT_INLINE(bool) verify_char(unsigned char c, unsigned int flags)
1612
1676
  {
1613
1677
  if ((flags & GIT_PATH_REJECT_BACKSLASH) && c == '\\')
@@ -1635,6 +1699,24 @@ GIT_INLINE(bool) verify_char(unsigned char c, unsigned int flags)
1635
1699
  return true;
1636
1700
  }
1637
1701
 
1702
+ /*
1703
+ * Return the length of the common prefix between str and prefix, comparing them
1704
+ * case-insensitively (must be ASCII to match).
1705
+ */
1706
+ GIT_INLINE(size_t) common_prefix_icase(const char *str, size_t len, const char *prefix)
1707
+ {
1708
+ size_t count = 0;
1709
+
1710
+ while (len >0 && tolower(*str) == tolower(*prefix)) {
1711
+ count++;
1712
+ str++;
1713
+ prefix++;
1714
+ len--;
1715
+ }
1716
+
1717
+ return count;
1718
+ }
1719
+
1638
1720
  /*
1639
1721
  * We fundamentally don't like some paths when dealing with user-inputted
1640
1722
  * strings (in checkout or ref names): we don't want dot or dot-dot
@@ -1648,6 +1730,7 @@ static bool verify_component(
1648
1730
  git_repository *repo,
1649
1731
  const char *component,
1650
1732
  size_t len,
1733
+ uint16_t mode,
1651
1734
  unsigned int flags)
1652
1735
  {
1653
1736
  if (len == 0)
@@ -1680,26 +1763,38 @@ static bool verify_component(
1680
1763
  return false;
1681
1764
  }
1682
1765
 
1683
- if (flags & GIT_PATH_REJECT_DOT_GIT_HFS &&
1684
- !verify_dotgit_hfs(component, len))
1685
- return false;
1766
+ if (flags & GIT_PATH_REJECT_DOT_GIT_HFS) {
1767
+ if (!verify_dotgit_hfs(component, len))
1768
+ return false;
1769
+ if (S_ISLNK(mode) && git_path_is_hfs_dotgit_modules(component, len))
1770
+ return false;
1771
+ }
1686
1772
 
1687
- if (flags & GIT_PATH_REJECT_DOT_GIT_NTFS &&
1688
- !verify_dotgit_ntfs(repo, component, len))
1689
- return false;
1773
+ if (flags & GIT_PATH_REJECT_DOT_GIT_NTFS) {
1774
+ if (!verify_dotgit_ntfs(repo, component, len))
1775
+ return false;
1776
+ if (S_ISLNK(mode) && git_path_is_ntfs_dotgit_modules(component, len))
1777
+ return false;
1778
+ }
1690
1779
 
1691
1780
  /* don't bother rerunning the `.git` test if we ran the HFS or NTFS
1692
1781
  * specific tests, they would have already rejected `.git`.
1693
1782
  */
1694
1783
  if ((flags & GIT_PATH_REJECT_DOT_GIT_HFS) == 0 &&
1695
- (flags & GIT_PATH_REJECT_DOT_GIT_NTFS) == 0 &&
1696
- (flags & GIT_PATH_REJECT_DOT_GIT_LITERAL) &&
1697
- len == 4 &&
1698
- component[0] == '.' &&
1699
- (component[1] == 'g' || component[1] == 'G') &&
1700
- (component[2] == 'i' || component[2] == 'I') &&
1701
- (component[3] == 't' || component[3] == 'T'))
1702
- return false;
1784
+ (flags & GIT_PATH_REJECT_DOT_GIT_NTFS) == 0 &&
1785
+ (flags & GIT_PATH_REJECT_DOT_GIT_LITERAL)) {
1786
+ if (len >= 4 &&
1787
+ component[0] == '.' &&
1788
+ (component[1] == 'g' || component[1] == 'G') &&
1789
+ (component[2] == 'i' || component[2] == 'I') &&
1790
+ (component[3] == 't' || component[3] == 'T')) {
1791
+ if (len == 4)
1792
+ return false;
1793
+
1794
+ if (S_ISLNK(mode) && common_prefix_icase(component, len, ".gitmodules") == len)
1795
+ return false;
1796
+ }
1797
+ }
1703
1798
 
1704
1799
  return true;
1705
1800
  }
@@ -1737,6 +1832,7 @@ GIT_INLINE(unsigned int) dotgit_flags(
1737
1832
  bool git_path_isvalid(
1738
1833
  git_repository *repo,
1739
1834
  const char *path,
1835
+ uint16_t mode,
1740
1836
  unsigned int flags)
1741
1837
  {
1742
1838
  const char *start, *c;
@@ -1750,14 +1846,14 @@ bool git_path_isvalid(
1750
1846
  return false;
1751
1847
 
1752
1848
  if (*c == '/') {
1753
- if (!verify_component(repo, start, (c - start), flags))
1849
+ if (!verify_component(repo, start, (c - start), mode, flags))
1754
1850
  return false;
1755
1851
 
1756
1852
  start = c+1;
1757
1853
  }
1758
1854
  }
1759
1855
 
1760
- return verify_component(repo, start, (c - start), flags);
1856
+ return verify_component(repo, start, (c - start), mode, flags);
1761
1857
  }
1762
1858
 
1763
1859
  int git_path_normalize_slashes(git_buf *out, const char *path)
@@ -1775,3 +1871,65 @@ int git_path_normalize_slashes(git_buf *out, const char *path)
1775
1871
 
1776
1872
  return 0;
1777
1873
  }
1874
+
1875
+ static int verify_dotgit_generic(const char *name, size_t len, const char *dotgit_name, size_t dotgit_len, const char *shortname_pfix)
1876
+ {
1877
+ if (!verify_dotgit_ntfs_generic(name, len, dotgit_name, dotgit_len, shortname_pfix))
1878
+ return false;
1879
+
1880
+ return verify_dotgit_hfs_generic(name, len, dotgit_name, dotgit_len);
1881
+ }
1882
+
1883
+ int git_path_is_ntfs_dotgit_modules(const char *name, size_t len)
1884
+ {
1885
+ return !verify_dotgit_ntfs_generic(name, len, "gitmodules", CONST_STRLEN("gitmodules"), "gi7eba");
1886
+ }
1887
+
1888
+ int git_path_is_hfs_dotgit_modules(const char *name, size_t len)
1889
+ {
1890
+ return !verify_dotgit_hfs_generic(name, len, "gitmodules", CONST_STRLEN("gitmodules"));
1891
+ }
1892
+
1893
+ int git_path_is_dotgit_modules(const char *name, size_t len)
1894
+ {
1895
+ if (git_path_is_hfs_dotgit_modules(name, len))
1896
+ return 1;
1897
+
1898
+ return git_path_is_ntfs_dotgit_modules(name, len);
1899
+ }
1900
+
1901
+ int git_path_is_ntfs_dotgit_ignore(const char *name, size_t len)
1902
+ {
1903
+ return !verify_dotgit_ntfs_generic(name, len, "gitignore", CONST_STRLEN("gitignore"), "gi250a");
1904
+ }
1905
+
1906
+ int git_path_is_hfs_dotgit_ignore(const char *name, size_t len)
1907
+ {
1908
+ return !verify_dotgit_hfs_generic(name, len, "gitignore", CONST_STRLEN("gitignore"));
1909
+ }
1910
+
1911
+ int git_path_is_dotgit_ignore(const char *name, size_t len)
1912
+ {
1913
+ if (git_path_is_hfs_dotgit_ignore(name, len))
1914
+ return 1;
1915
+
1916
+ return git_path_is_ntfs_dotgit_ignore(name, len);
1917
+ }
1918
+
1919
+ int git_path_is_hfs_dotgit_attributes(const char *name, size_t len)
1920
+ {
1921
+ return !verify_dotgit_hfs_generic(name, len, "gitattributes", CONST_STRLEN("gitattributes"));
1922
+ }
1923
+
1924
+ int git_path_is_ntfs_dotgit_attributes(const char *name, size_t len)
1925
+ {
1926
+ return !verify_dotgit_ntfs_generic(name, len, "gitattributes", CONST_STRLEN("gitattributes"), "gi7d29");
1927
+ }
1928
+
1929
+ int git_path_is_dotgit_attributes(const char *name, size_t len)
1930
+ {
1931
+ if (git_path_is_hfs_dotgit_attributes(name, len))
1932
+ return 1;
1933
+
1934
+ return git_path_is_ntfs_dotgit_attributes(name, len);
1935
+ }
@@ -637,6 +637,7 @@ extern int git_path_from_url_or_path(git_buf *local_path_out, const char *url_or
637
637
  extern bool git_path_isvalid(
638
638
  git_repository *repo,
639
639
  const char *path,
640
+ uint16_t mode,
640
641
  unsigned int flags);
641
642
 
642
643
  /**
@@ -644,4 +645,76 @@ extern bool git_path_isvalid(
644
645
  */
645
646
  int git_path_normalize_slashes(git_buf *out, const char *path);
646
647
 
648
+ /**
649
+ * Check whether a path component corresponds to a .gitmodules file
650
+ *
651
+ * @param name the path component to check
652
+ * @param len the length of `name`
653
+ */
654
+ extern int git_path_is_dotgit_modules(const char *name, size_t len);
655
+
656
+ /**
657
+ * Check whether a path component corresponds to a .gitmodules file in NTFS
658
+ *
659
+ * @param name the path component to check
660
+ * @param len the length of `name`
661
+ */
662
+ extern int git_path_is_ntfs_dotgit_modules(const char *name, size_t len);
663
+
664
+ /**
665
+ * Check whether a path component corresponds to a .gitmodules file in HFS+
666
+ *
667
+ * @param name the path component to check
668
+ * @param len the length of `name`
669
+ */
670
+ extern int git_path_is_hfs_dotgit_modules(const char *name, size_t len);
671
+
672
+ /**
673
+ * Check whether a path component corresponds to a .gitignore file
674
+ *
675
+ * @param name the path component to check
676
+ * @param len the length of `name`
677
+ */
678
+ extern int git_path_is_dotgit_ignore(const char *name, size_t len);
679
+
680
+ /**
681
+ * Check whether a path component corresponds to a .gitignore file in NTFS
682
+ *
683
+ * @param name the path component to check
684
+ * @param len the length of `name`
685
+ */
686
+ extern int git_path_is_ntfs_dotgit_ignore(const char *name, size_t len);
687
+
688
+ /**
689
+ * Check whether a path component corresponds to a .gitignore file in HFS+
690
+ *
691
+ * @param name the path component to check
692
+ * @param len the length of `name`
693
+ */
694
+ extern int git_path_is_hfs_dotgit_ignore(const char *name, size_t len);
695
+
696
+ /**
697
+ * Check whether a path component corresponds to a .gitignore file
698
+ *
699
+ * @param name the path component to check
700
+ * @param len the length of `name`
701
+ */
702
+ extern int git_path_is_dotgit_attributes(const char *name, size_t len);
703
+
704
+ /**
705
+ * Check whether a path component corresponds to a .gitattributes file in NTFS
706
+ *
707
+ * @param name the path component to check
708
+ * @param len the length of `name`
709
+ */
710
+ extern int git_path_is_ntfs_dotgit_attributes(const char *name, size_t len);
711
+
712
+ /**
713
+ * Check whether a path component corresponds to a .gitattributes file in HFS+
714
+ *
715
+ * @param name the path component to check
716
+ * @param len the length of `name`
717
+ */
718
+ extern int git_path_is_hfs_dotgit_attributes(const char *name, size_t len);
719
+
647
720
  #endif
@@ -744,7 +744,7 @@ static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *
744
744
 
745
745
  assert(file && backend && name);
746
746
 
747
- if (!git_path_isvalid(backend->repo, name, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
747
+ if (!git_path_isvalid(backend->repo, name, 0, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
748
748
  giterr_set(GITERR_INVALID, "invalid reference name '%s'", name);
749
749
  return GIT_EINVALIDSPEC;
750
750
  }
@@ -1740,7 +1740,7 @@ static int lock_reflog(git_filebuf *file, refdb_fs_backend *backend, const char
1740
1740
 
1741
1741
  repo = backend->repo;
1742
1742
 
1743
- if (!git_path_isvalid(backend->repo, refname, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
1743
+ if (!git_path_isvalid(backend->repo, refname, 0, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
1744
1744
  giterr_set(GITERR_INVALID, "invalid reference name '%s'", refname);
1745
1745
  return GIT_EINVALIDSPEC;
1746
1746
  }
@@ -169,13 +169,13 @@ static void free_submodule_names(git_strmap *names)
169
169
  * TODO: for some use-cases, this might need case-folding on a
170
170
  * case-insensitive filesystem
171
171
  */
172
- static int load_submodule_names(git_strmap *out, git_config *cfg)
172
+ static int load_submodule_names(git_strmap *out, git_repository *repo, git_config *cfg)
173
173
  {
174
174
  const char *key = "submodule\\..*\\.path";
175
175
  git_config_iterator *iter;
176
176
  git_config_entry *entry;
177
177
  git_buf buf = GIT_BUF_INIT;
178
- int rval;
178
+ int rval, isvalid;
179
179
  int error = 0;
180
180
 
181
181
  if ((error = git_config_iterator_glob_new(&iter, cfg, key)) < 0)
@@ -186,16 +186,29 @@ static int load_submodule_names(git_strmap *out, git_config *cfg)
186
186
  fdot = strchr(entry->name, '.');
187
187
  ldot = strrchr(entry->name, '.');
188
188
 
189
+ git_buf_clear(&buf);
189
190
  git_buf_put(&buf, fdot + 1, ldot - fdot - 1);
191
+ isvalid = git_submodule_name_is_valid(repo, buf.ptr, 0);
192
+ if (isvalid < 0) {
193
+ error = isvalid;
194
+ goto out;
195
+ }
196
+ if (!isvalid)
197
+ continue;
198
+
190
199
  git_strmap_insert(out, entry->value, git_buf_detach(&buf), &rval);
191
200
  if (rval < 0) {
192
201
  giterr_set(GITERR_NOMEMORY, "error inserting submodule into hash table");
193
202
  return -1;
194
203
  }
195
204
  }
205
+ if (error == GIT_ITEROVER)
206
+ error = 0;
196
207
 
208
+ out:
209
+ git_buf_free(&buf);
197
210
  git_config_iterator_free(iter);
198
- return 0;
211
+ return error;
199
212
  }
200
213
 
201
214
  int git_submodule_lookup(
@@ -314,6 +327,28 @@ int git_submodule_lookup(
314
327
  return 0;
315
328
  }
316
329
 
330
+ int git_submodule_name_is_valid(git_repository *repo, const char *name, int flags)
331
+ {
332
+ git_buf buf = GIT_BUF_INIT;
333
+ int error, isvalid;
334
+
335
+ if (flags == 0)
336
+ flags = GIT_PATH_REJECT_FILESYSTEM_DEFAULTS;
337
+
338
+ /* Avoid allocating a new string if we can avoid it */
339
+ if (strchr(name, '\\') != NULL) {
340
+ if ((error = git_path_normalize_slashes(&buf, name)) < 0)
341
+ return error;
342
+ } else {
343
+ git_buf_attach_notowned(&buf, name, strlen(name));
344
+ }
345
+
346
+ isvalid = git_path_isvalid(repo, buf.ptr, 0, flags);
347
+ git_buf_free(&buf);
348
+
349
+ return isvalid;
350
+ }
351
+
317
352
  static void submodule_free_dup(void *sm)
318
353
  {
319
354
  git_submodule_free(sm);
@@ -359,7 +394,7 @@ static int submodules_from_index(git_strmap *map, git_index *idx, git_config *cf
359
394
  git_strmap *names = 0;
360
395
 
361
396
  git_strmap_alloc(&names);
362
- if ((error = load_submodule_names(names, cfg)))
397
+ if ((error = load_submodule_names(names, git_index_owner(idx), cfg)))
363
398
  goto done;
364
399
 
365
400
  if ((error = git_iterator_for_index(&i, git_index_owner(idx), idx, NULL)) < 0)
@@ -411,7 +446,7 @@ static int submodules_from_head(git_strmap *map, git_tree *head, git_config *cfg
411
446
  const git_index_entry *entry;
412
447
  git_strmap *names = 0;
413
448
  git_strmap_alloc(&names);
414
- if ((error = load_submodule_names(names, cfg)))
449
+ if ((error = load_submodule_names(names, git_tree_owner(head), cfg)))
415
450
  goto done;
416
451
 
417
452
  if ((error = git_iterator_for_tree(&i, head, NULL)) < 0)
@@ -1502,13 +1537,19 @@ static int submodule_update_head(git_submodule *submodule)
1502
1537
 
1503
1538
  int git_submodule_reload(git_submodule *sm, int force)
1504
1539
  {
1505
- int error = 0;
1540
+ int error = 0, isvalid;
1506
1541
  git_config *mods;
1507
1542
 
1508
1543
  GIT_UNUSED(force);
1509
1544
 
1510
1545
  assert(sm);
1511
1546
 
1547
+ isvalid = git_submodule_name_is_valid(sm->repo, sm->name, 0);
1548
+ if (isvalid <= 0) {
1549
+ /* This should come with a warning, but we've no API for that */
1550
+ return isvalid;
1551
+ }
1552
+
1512
1553
  if (!git_repository_is_bare(sm->repo)) {
1513
1554
  /* refresh config data */
1514
1555
  mods = gitmodules_snapshot(sm->repo);
@@ -1849,7 +1890,7 @@ static int submodule_load_each(const git_config_entry *entry, void *payload)
1849
1890
  git_strmap *map = data->map;
1850
1891
  git_buf name = GIT_BUF_INIT;
1851
1892
  git_submodule *sm;
1852
- int error;
1893
+ int error, isvalid;
1853
1894
 
1854
1895
  if (git__prefixcmp(entry->name, "submodule.") != 0)
1855
1896
  return 0;
@@ -1865,6 +1906,12 @@ static int submodule_load_each(const git_config_entry *entry, void *payload)
1865
1906
  if ((error = git_buf_set(&name, namestart, property - namestart -1)) < 0)
1866
1907
  return error;
1867
1908
 
1909
+ isvalid = git_submodule_name_is_valid(data->repo, name.ptr, 0);
1910
+ if (isvalid <= 0) {
1911
+ error = isvalid;
1912
+ goto done;
1913
+ }
1914
+
1868
1915
  /*
1869
1916
  * Now that we have the submodule's name, we can use that to
1870
1917
  * figure out whether it's in the map. If it's not, we create
@@ -148,4 +148,17 @@ extern int git_submodule_parse_update(
148
148
  extern int git_submodule__map(
149
149
  git_repository *repo,
150
150
  git_strmap *map);
151
+
152
+ /**
153
+ * Check whether a submodule's name is valid.
154
+ *
155
+ * Check the path against the path validity rules, either the filesystem
156
+ * defaults (like checkout does) or whichever you want to compare against.
157
+ *
158
+ * @param repo the repository which contains the submodule
159
+ * @param name the name to check
160
+ * @param flags the `GIT_PATH` flags to use for the check (0 to use filesystem defaults)
161
+ */
162
+ extern int git_submodule_name_is_valid(git_repository *repo, const char *name, int flags);
163
+
151
164
  #endif
@@ -54,7 +54,7 @@ GIT_INLINE(git_filemode_t) normalize_filemode(git_filemode_t filemode)
54
54
  static int valid_entry_name(git_repository *repo, const char *filename)
55
55
  {
56
56
  return *filename != '\0' &&
57
- git_path_isvalid(repo, filename,
57
+ git_path_isvalid(repo, filename, 0,
58
58
  GIT_PATH_REJECT_TRAVERSAL | GIT_PATH_REJECT_DOT_GIT | GIT_PATH_REJECT_SLASH);
59
59
  }
60
60
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rugged
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.0
4
+ version: 0.27.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Chacon
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-03-26 00:00:00.000000000 Z
12
+ date: 2018-05-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake-compiler