summaryrefslogtreecommitdiff
path: root/read-cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'read-cache.c')
-rw-r--r--read-cache.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/read-cache.c b/read-cache.c
index 54573ce2ee..f458f50458 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -5,6 +5,7 @@
*/
#include "cache.h"
#include "cache-tree.h"
+#include "refs.h"
/* Index extensions.
*
@@ -91,6 +92,23 @@ static int ce_compare_link(struct cache_entry *ce, size_t expected_size)
return match;
}
+static int ce_compare_gitlink(struct cache_entry *ce)
+{
+ unsigned char sha1[20];
+
+ /*
+ * We don't actually require that the .git directory
+ * under DIRLNK directory be a valid git directory. It
+ * might even be missing (in case nobody populated that
+ * sub-project).
+ *
+ * If so, we consider it always to match.
+ */
+ if (resolve_gitlink_ref(ce->name, "HEAD", sha1) < 0)
+ return 0;
+ return hashcmp(sha1, ce->sha1);
+}
+
static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st)
{
switch (st->st_mode & S_IFMT) {
@@ -102,6 +120,9 @@ static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st)
if (ce_compare_link(ce, xsize_t(st->st_size)))
return DATA_CHANGED;
break;
+ case S_IFDIRLNK:
+ /* No need to do anything, we did the exact compare in "match_stat_basic" */
+ break;
default:
return TYPE_CHANGED;
}
@@ -127,6 +148,12 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
(has_symlinks || !S_ISREG(st->st_mode)))
changed |= TYPE_CHANGED;
break;
+ case S_IFDIRLNK:
+ if (!S_ISDIR(st->st_mode))
+ changed |= TYPE_CHANGED;
+ else if (ce_compare_gitlink(ce))
+ changed |= DATA_CHANGED;
+ break;
default:
die("internal error: ce_mode is %o", ntohl(ce->ce_mode));
}
@@ -250,9 +277,9 @@ int base_name_compare(const char *name1, int len1, int mode1,
return cmp;
c1 = name1[len];
c2 = name2[len];
- if (!c1 && S_ISDIR(mode1))
+ if (!c1 && (S_ISDIR(mode1) || S_ISDIRLNK(mode1)))
c1 = '/';
- if (!c2 && S_ISDIR(mode2))
+ if (!c2 && (S_ISDIR(mode2) || S_ISDIRLNK(mode2)))
c2 = '/';
return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;
}
@@ -334,8 +361,8 @@ int add_file_to_cache(const char *path, int verbose)
if (lstat(path, &st))
die("%s: unable to stat (%s)", path, strerror(errno));
- if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
- die("%s: can only add regular files or symbolic links", path);
+ if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode))
+ die("%s: can only add regular files, symbolic links or git-directories", path);
namelen = strlen(path);
size = cache_entry_size(namelen);