[PATCH v4 5/8] convert: Added core.refilteronadd feature.
Show changes to 6 files +105 −0
Documentation/config.txt, cache.h, config.c, environment.c, sha1_file.c, t/t0021-conversion.sh
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 4eb3ab3..5225047 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -535,6 +535,12 @@ core.sparseCheckout::
Enable "sparse checkout" feature. See section "Sparse checkout" in
linkgit:git-read-tree[1] for more information.
+core.refilterOnAdd::
+ Enable "refilter on add" feature. This causes source files to be
+ behave as if they were checked out after a linkgit:git-add[1].
+ This is typically usefull if eg the `ident` attribute is active,
+ in which case the $Id$ tags will be updated.
+
core.refilterOnDiff::
Enable "refilter on diff" feature. This causes source files that
have only changed from the committed version as a side effect of
diff --git a/cache.h b/cache.h
index cd2bca4..1bd8484 100644
--- a/cache.h
+++ b/cache.h
@@ -552,6 +552,7 @@ extern int read_replace_refs;
extern int fsync_object_files;
extern int core_preload_index;
extern int core_apply_sparse_checkout;
+extern int core_refilter_on_add;
extern int core_refilter_on_diff;
enum safe_crlf {
diff --git a/config.c b/config.c
index 4954797..d284897 100644
--- a/config.c
+++ b/config.c
@@ -523,6 +523,11 @@ static int git_default_core_config(const char *var, const char *value)
return 0;
}
+ if (!strcmp(var, "core.refilteronadd")) {
+ core_refilter_on_add = git_config_bool(var, value);
+ return 0;
+ }
+
if(!strcmp(var, "core.refilterondiff")) {
core_refilter_on_diff = git_config_bool(var, value);
return 0;
diff --git a/environment.c b/environment.c
index 1b52bed..4b4c966 100644
--- a/environment.c
+++ b/environment.c
@@ -52,6 +52,7 @@ enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
char *notes_ref_name;
int grafts_replace_parents = 1;
int core_apply_sparse_checkout;
+int core_refilter_on_add;
int core_refilter_on_diff;
/* Parallel index stat data preload? */
diff --git a/sha1_file.c b/sha1_file.c
index a08a9d0..2aa800e 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2466,6 +2466,54 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
return ret;
}
+static int refilter_fd(int fd, struct stat *st, const char *path)
+{
+ int ret = -1;
+ size_t size = xsize_t(st->st_size);
+ struct strbuf gbuf = STRBUF_INIT;
+
+ if (!S_ISREG(st->st_mode)) {
+ struct strbuf sbuf = STRBUF_INIT;
+ if (strbuf_read(&sbuf, fd, 4096) >= 0)
+ ret = convert_to_git(path, sbuf.buf, sbuf.len, &gbuf, safe_crlf);
+ else
+ ret = -1;
+ strbuf_release(&sbuf);
+ } else if (size) {
+ void *buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+ ret = convert_to_git(path, buf, size, &gbuf, safe_crlf);
+ munmap(buf, size);
+ } else
+ ret = -1;
+
+ if (ret > 0) {
+ /* Something happened during conversion to git.
+ * Now convert it back, and save the result.
+ */
+ struct strbuf obuf = STRBUF_INIT;
+
+ lseek(fd, 0, SEEK_SET);
+
+ if (convert_to_working_tree(path, gbuf.buf, gbuf.len, &obuf)) {
+ if (write_or_whine(fd, obuf.buf, obuf.len, path))
+ ftruncate(fd, obuf.len);
+ else
+ ret = -1;
+ } else {
+ if (write_or_whine(fd, gbuf.buf, gbuf.len, path))
+ ftruncate(fd, gbuf.len);
+ else
+ ret = -1;
+ }
+
+ strbuf_release(&obuf);
+ }
+ strbuf_release(&gbuf);
+
+ close(fd);
+ return ret;
+}
+
int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object)
{
int fd;
@@ -2480,6 +2528,15 @@ int index_path(unsigned char *sha1, const char *path, struct stat *st, int write
if (index_fd(sha1, fd, st, write_object, OBJ_BLOB, path) < 0)
return error("%s: failed to insert into database",
path);
+ if (write_object && core_refilter_on_add) {
+ fd = open(path, O_RDWR);
+ if (fd < 0)
+ return error("open(\"%s\"): %s", path,
+ strerror(errno));
+ if (refilter_fd(fd, st, path) < 0)
+ return error("%s: failed to refilter file",
+ path);
+ }
break;
case S_IFLNK:
if (strbuf_readlink(&sb, path, st->st_size)) {
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
index 48ae8bb..9ddbde3 100755
--- a/t/t0021-conversion.sh
+++ b/t/t0021-conversion.sh
@@ -118,4 +118,39 @@ test_expect_success keywords_not_modified '
test "x`git status --porcelain -- expanded-keywords2`" = x
'
+# Check that keywords are expanded on add when refilter is enabled.
+test_expect_success expanded_on_add '
+ git config --add core.refilteronadd true
+
+ echo "expanded-keywords3 ident" >> .gitattributes &&
+
+ {
+ echo "File with keyword"
+ echo "\$Id\$"
+ } > expanded-keywords3 &&
+
+ {
+ echo "File with keyword"
+ echo "\$Id: 0661580d6f976fe7cc1e4512f8db3f2ddb8d93cc \$"
+ } > expected-output3 &&
+
+ git add expanded-keywords3 &&
+
+ cat expanded-keywords3 &&
+ cmp expanded-keywords3 expected-output3
+'
+
+# Check that keywords are expanded on commit when refilter is enabled.
+test_expect_success expanded_on_commit '
+ {
+ echo "File with keyword"
+ echo "\$Id\$"
+ } > expanded-keywords3 &&
+
+ git commit -m "File with keyword" expanded-keywords3 &&
+
+ cat expanded-keywords3 &&
+ cmp expanded-keywords3 expected-output3
+'
+
test_done