summaryrefslogtreecommitdiff
path: root/upload-pack.c
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2016-06-12 10:54:09 (GMT)
committerJunio C Hamano <gitster@pobox.com>2016-06-13 21:38:16 (GMT)
commitcccf74e2da85808478c784e403a69bbfe2b9f518 (patch)
treedd1a8c3e3da2256f28894ea98e31ebc1a4ce8918 /upload-pack.c
parent079aa97e24daff1329f041e00ba621b0afd59163 (diff)
downloadgit-cccf74e2da85808478c784e403a69bbfe2b9f518.zip
git-cccf74e2da85808478c784e403a69bbfe2b9f518.tar.gz
git-cccf74e2da85808478c784e403a69bbfe2b9f518.tar.bz2
fetch, upload-pack: --deepen=N extends shallow boundary by N commits
In git-fetch, --depth argument is always relative with the latest remote refs. This makes it a bit difficult to cover this use case, where the user wants to make the shallow history, say 3 levels deeper. It would work if remote refs have not moved yet, but nobody can guarantee that, especially when that use case is performed a couple months after the last clone or "git fetch --depth". Also, modifying shallow boundary using --depth does not work well with clones created by --since or --not. This patch fixes that. A new argument --deepen=<N> will add <N> more (*) parent commits to the current history regardless of where remote refs are. Have/Want negotiation is still respected. So if remote refs move, the server will send two chunks: one between "have" and "want" and another to extend shallow history. In theory, the client could send no "want"s in order to get the second chunk only. But the protocol does not allow that. Either you send no want lines, which means ls-remote; or you have to send at least one want line that carries deep-relative to the server.. The main work was done by Dongcan Jiang. I fixed it up here and there. And of course all the bugs belong to me. (*) We could even support --deepen=<N> where <N> is negative. In that case we can cut some history from the shallow clone. This operation (and --depth=<shorter depth>) does not require interaction with remote side (and more complicated to implement as a result). Helped-by: Duy Nguyen <pclouds@gmail.com> Helped-by: Eric Sunshine <sunshine@sunshineco.com> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Dongcan Jiang <dongcan.jiang@gmail.com> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'upload-pack.c')
-rw-r--r--upload-pack.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/upload-pack.c b/upload-pack.c
index 3227df8..e40d15a 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -32,6 +32,7 @@ static const char upload_pack_usage[] = "git upload-pack [--strict] [--timeout=<
static unsigned long oldest_have;
+static int deepen_relative;
static int multi_ack;
static int no_done;
static int use_thin_pack, use_ofs_delta, use_include_tag;
@@ -674,7 +675,8 @@ static void send_unshallow(const struct object_array *shallows)
}
}
-static void deepen(int depth, const struct object_array *shallows)
+static void deepen(int depth, int deepen_relative,
+ struct object_array *shallows)
{
if (depth == INFINITE_DEPTH && !is_repository_shallow()) {
int i;
@@ -683,6 +685,17 @@ static void deepen(int depth, const struct object_array *shallows)
struct object *object = shallows->objects[i].item;
object->flags |= NOT_SHALLOW;
}
+ } else if (deepen_relative) {
+ struct object_array reachable_shallows = OBJECT_ARRAY_INIT;
+ struct commit_list *result;
+
+ get_reachable_list(shallows, &reachable_shallows);
+ result = get_shallow_commits(&reachable_shallows,
+ depth + 1,
+ SHALLOW, NOT_SHALLOW);
+ send_shallow(result);
+ free_commit_list(result);
+ object_array_clear(&reachable_shallows);
} else {
struct commit_list *result;
@@ -779,6 +792,8 @@ static void receive_needs(void)
features = arg + 40;
+ if (parse_feature_request(features, "deepen-relative"))
+ deepen_relative = 1;
if (parse_feature_request(features, "multi_ack_detailed"))
multi_ack = 2;
else if (parse_feature_request(features, "multi_ack"))
@@ -828,7 +843,7 @@ static void receive_needs(void)
if (depth > 0 && deepen_rev_list)
die("git upload-pack: deepen and deepen-since (or deepen-not) cannot be used together");
if (depth > 0)
- deepen(depth, &shallows);
+ deepen(depth, deepen_relative, &shallows);
else if (deepen_rev_list) {
struct argv_array av = ARGV_ARRAY_INIT;
int i;
@@ -899,8 +914,8 @@ static int send_ref(const char *refname, const struct object_id *oid,
int flag, void *cb_data)
{
static const char *capabilities = "multi_ack thin-pack side-band"
- " side-band-64k ofs-delta shallow deepen-since deepen-not no-progress"
- " include-tag multi_ack_detailed";
+ " side-band-64k ofs-delta shallow deepen-since deepen-not"
+ " deepen-relative no-progress include-tag multi_ack_detailed";
const char *refname_nons = strip_namespace(refname);
struct object_id peeled;