rugged 0.27.0 → 0.27.1

Sign up to get free protection for your applications and to get access to all the features.
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