@@ -761,4 +761,18 @@ core.maxTreeDepth::
core.maxSymlinkDepth::
The maximum number of symlinks Git is willing to resolve while
looking for a tree entry.
- The default is GET_TREE_ENTRY_FOLLOW_SYMLINKS_MAX_LINKS.
\ No newline at end of file
+ The default is GET_TREE_ENTRY_FOLLOW_SYMLINKS_MAX_LINKS.
+
+core.symlinkResolutionMode::
+ The result returned by the symlink resolution process when
+ core.maxSymlinkDepth is reached. When set to "error"
+ `
+ loop SP <size> LF
+ <object> LF
+ ` is returned.
+ If `best-effort` is set, the resolution process will return
+ something like:
+ `
+ <oid> blob <size> 120000\nname\n
+ `
+ The default is "error".
\ No newline at end of file
@@ -1687,6 +1687,19 @@ static int git_default_core_config(const char *var, const char *value,
return 0;
}
+ if (!strcmp(var, "core.symlinkresolutionmode")) {
+ if (!value)
+ symlink_resolution_mode = SYMLINK_RESOLUTION_MODE_ERROR;
+ if (!strcmp(value, "error"))
+ symlink_resolution_mode = SYMLINK_RESOLUTION_MODE_ERROR;
+ else if (!strcmp(value, "best-effort"))
+ symlink_resolution_mode =
+ SYMLINK_RESOLUTION_MODE_BEST_EFFORT;
+ else
+ warning(_("ignoring unknown core.symlinkresolutionmode value '%s'"),
+ value);
+ }
+
/* Add other config variables here and to Documentation/config.txt. */
return platform_core_config(var, value, ctx, cb);
}
@@ -96,6 +96,8 @@ int max_allowed_tree_depth =
2048;
#endif
int max_symlink_depth = -1;
+enum symlink_resolution_mode symlink_resolution_mode =
+ SYMLINK_RESOLUTION_MODE_ERROR;
#ifndef PROTECT_HFS_DEFAULT
#define PROTECT_HFS_DEFAULT 0
@@ -143,6 +143,13 @@ extern unsigned long pack_size_limit_cfg;
extern int max_allowed_tree_depth;
extern int max_symlink_depth;
+enum symlink_resolution_mode {
+ SYMLINK_RESOLUTION_MODE_ERROR = 0,
+ SYMLINK_RESOLUTION_MODE_BEST_EFFORT
+};
+
+extern enum symlink_resolution_mode symlink_resolution_mode;
+
/*
* Accessors for the core.sharedrepository config which lazy-load the value
* from the config (if not already set). The "reset" function can be
@@ -1113,6 +1113,35 @@ test_expect_success 'git cat-file --batch --follow-symlink stop resolving symlin
test_cmp expect actual
'
+test_expect_success 'git cat-file --batch --follow-symlink stop resolving symlink at designated depth with error mode config' '
+ printf "loop 22\nHEAD:link-to-symlink-3\n">expect &&
+ printf 'HEAD:link-to-symlink-3' | git -c core.maxsymlinkdepth=1 -c core.symlinkresolutionmode=error cat-file --batch="%(objectname) %(objecttype) %(objectsize)" --follow-symlinks > actual &&
+ test_cmp expect actual &&
+ printf 'HEAD:link-to-symlink-3' | git -c core.maxsymlinkdepth=2 -c core.symlinkresolutionmode=error cat-file --batch="%(objectname) %(objecttype) %(objectsize)" --follow-symlinks > actual &&
+ test_cmp expect actual &&
+ printf 'HEAD:link-to-symlink-3' | git -c core.maxsymlinkdepth=3 -c core.symlinkresolutionmode=error cat-file --batch="%(objectname) %(objecttype) %(objectsize)" --follow-symlinks > actual &&
+ test_cmp expect actual &&
+ oid=$(git rev-parse HEAD:morx) &&
+ printf "${oid} blob 11\nHello World\n" >expect &&
+ printf 'HEAD:link-to-symlink-3' | git -c core.maxsymlinkdepth=4 cat-file --batch="%(objectname) %(objecttype) %(objectsize)" --follow-symlinks > actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git cat-file --batch --follow-symlink return object info at designated depth' '
+ oid=$(git rev-parse HEAD:link-to-symlink-1) &&
+ printf "${oid} blob 13\nsame-dir-link\n" >expect &&
+ printf 'HEAD:link-to-symlink-1' | git -c core.maxsymlinkdepth=1 -c core.symlinkresolutionmode=best-effort cat-file --batch="%(objectname) %(objecttype) %(objectsize)" --follow-symlinks >actual &&
+ test_cmp expect actual &&
+ oid=$(git rev-parse HEAD:same-dir-link) &&
+ printf "${oid} blob 4\nmorx\n" > expect &&
+ printf 'HEAD:link-to-symlink-1' | git -c core.maxsymlinkdepth=2 -c core.symlinkresolutionmode=best-effort cat-file --batch="%(objectname) %(objecttype) %(objectsize)" --follow-symlinks >actual &&
+ test_cmp expect actual &&
+ oid=$(git rev-parse HEAD:morx) &&
+ printf "${oid} blob 11\nHello World\n" > expect &&
+ printf 'HEAD:link-to-symlink-1' | git -c core.maxsymlinkdepth=3 -c core.symlinkresolutionmode=best-effort cat-file --batch="%(objectname) %(objecttype) %(objectsize)" --follow-symlinks >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'cat-file --batch-all-objects shows all objects' '
# make new repos so we know the full set of objects; we will
# also make sure that there are some packed and some loose
@@ -821,6 +821,17 @@ enum get_oid_result get_tree_entry_follow_symlinks(struct repository *r,
contents_start = contents;
parent = &parents[parents_nr - 1];
+
+ if (follows_remaining == 0 &&
+ symlink_resolution_mode ==
+ SYMLINK_RESOLUTION_MODE_BEST_EFFORT) {
+ strbuf_addstr(result_path, contents);
+ oidcpy(result, ¤t_tree_oid);
+ free(contents);
+ retval = FOUND;
+ goto done;
+ }
+
init_tree_desc(&t, &parent->oid, parent->tree, parent->size);
strbuf_splice(&namebuf, 0, len,
contents_start, link_len);