Skip to content

Commit

Permalink
Merge branch 'nd/shallow-deepen'
Browse files Browse the repository at this point in the history
The existing "git fetch --depth=<n>" option was hard to use
correctly when making the history of an existing shallow clone
deeper.  A new option, "--deepen=<n>", has been added to make this
easier to use.  "git clone" also learned "--shallow-since=<date>"
and "--shallow-exclude=<tag>" options to make it easier to specify
"I am interested only in the recent N months worth of history" and
"Give me only the history since that version".

* nd/shallow-deepen: (27 commits)
  fetch, upload-pack: --deepen=N extends shallow boundary by N commits
  upload-pack: add get_reachable_list()
  upload-pack: split check_unreachable() in two, prep for get_reachable_list()
  t5500, t5539: tests for shallow depth excluding a ref
  clone: define shallow clone boundary with --shallow-exclude
  fetch: define shallow boundary with --shallow-exclude
  upload-pack: support define shallow boundary by excluding revisions
  refs: add expand_ref()
  t5500, t5539: tests for shallow depth since a specific date
  clone: define shallow clone boundary based on time with --shallow-since
  fetch: define shallow boundary with --shallow-since
  upload-pack: add deepen-since to cut shallow repos based on time
  shallow.c: implement a generic shallow boundary finder based on rev-list
  fetch-pack: use a separate flag for fetch in deepening mode
  fetch-pack.c: mark strings for translating
  fetch-pack: use a common function for verbose printing
  fetch-pack: use skip_prefix() instead of starts_with()
  upload-pack: move rev-list code out of check_non_tip()
  upload-pack: make check_non_tip() clean things up on error
  upload-pack: tighten number parsing at "deepen" lines
  ...
  • Loading branch information
gitster committed Oct 10, 2016
2 parents a229a30 + cccf74e commit a460ea4
Show file tree
Hide file tree
Showing 23 changed files with 890 additions and 224 deletions.
14 changes: 14 additions & 0 deletions Documentation/fetch-options.txt
Expand Up @@ -14,6 +14,20 @@
linkgit:git-clone[1]), deepen or shorten the history to the specified
number of commits. Tags for the deepened commits are not fetched.

--deepen=<depth>::
Similar to --depth, except it specifies the number of commits
from the current shallow boundary instead of from the tip of
each remote branch history.

--shallow-since=<date>::
Deepen or shorten the history of a shallow repository to
include all reachable commits after <date>.

--shallow-exclude=<revision>::
Deepen or shorten the history of a shallow repository to
exclude commits reachable from a specified remote branch or tag.
This option can be specified multiple times.

--unshallow::
If the source repository is complete, convert a shallow
repository to a complete one, removing all the limitations
Expand Down
8 changes: 8 additions & 0 deletions Documentation/git-clone.txt
Expand Up @@ -197,6 +197,14 @@ objects from the source repository into a pack in the cloned repository.
tips of all branches. If you want to clone submodules shallowly,
also pass `--shallow-submodules`.

--shallow-since=<date>::
Create a shallow clone with a history after the specified time.

--shallow-exclude=<revision>::
Create a shallow clone with a history, excluding commits
reachable from a specified remote branch or tag. This option
can be specified multiple times.

--[no-]single-branch::
Clone only the history leading to the tip of a single branch,
either specified by the `--branch` option or the primary
Expand Down
14 changes: 14 additions & 0 deletions Documentation/git-fetch-pack.txt
Expand Up @@ -87,6 +87,20 @@ be in a separate packet, and the list must end with a flush packet.
'git-upload-pack' treats the special depth 2147483647 as
infinite even if there is an ancestor-chain that long.

--shallow-since=<date>::
Deepen or shorten the history of a shallow'repository to
include all reachable commits after <date>.

--shallow-exclude=<revision>::
Deepen or shorten the history of a shallow repository to
exclude commits reachable from a specified remote branch or tag.
This option can be specified multiple times.

--deepen-relative::
Argument --depth specifies the number of commits from the
current shallow boundary instead of from the tip of each
remote branch history.

--no-progress::
Do not show the progress.

Expand Down
11 changes: 11 additions & 0 deletions Documentation/gitremote-helpers.txt
Expand Up @@ -415,6 +415,17 @@ set by Git if the remote helper has the 'option' capability.
'option depth' <depth>::
Deepens the history of a shallow repository.

'option deepen-since <timestamp>::
Deepens the history of a shallow repository based on time.

'option deepen-not <ref>::
Deepens the history of a shallow repository excluding ref.
Multiple options add up.

'option deepen-relative {'true'|'false'}::
Deepens the history of a shallow repository relative to
current boundary. Only valid when used with "option depth".

'option followtags' {'true'|'false'}::
If enabled the helper should automatically fetch annotated
tag objects if the object the tag points at was transferred
Expand Down
4 changes: 3 additions & 1 deletion Documentation/technical/pack-protocol.txt
Expand Up @@ -219,7 +219,9 @@ out of what the server said it could do with the first 'want' line.

shallow-line = PKT-LINE("shallow" SP obj-id)

depth-request = PKT-LINE("deepen" SP depth)
depth-request = PKT-LINE("deepen" SP depth) /
PKT-LINE("deepen-since" SP timestamp) /
PKT-LINE("deepen-not" SP ref)

first-want = PKT-LINE("want" SP obj-id SP capability-list)
additional-want = PKT-LINE("want" SP obj-id)
Expand Down
25 changes: 25 additions & 0 deletions Documentation/technical/protocol-capabilities.txt
Expand Up @@ -179,6 +179,31 @@ This capability adds "deepen", "shallow" and "unshallow" commands to
the fetch-pack/upload-pack protocol so clients can request shallow
clones.

deepen-since
------------

This capability adds "deepen-since" command to fetch-pack/upload-pack
protocol so the client can request shallow clones that are cut at a
specific time, instead of depth. Internally it's equivalent of doing
"rev-list --max-age=<timestamp>" on the server side. "deepen-since"
cannot be used with "deepen".

deepen-not
----------

This capability adds "deepen-not" command to fetch-pack/upload-pack
protocol so the client can request shallow clones that are cut at a
specific revision, instead of depth. Internally it's equivalent of
doing "rev-list --not <rev>" on the server side. "deepen-not"
cannot be used with "deepen", but can be used with "deepen-since".

deepen-relative
---------------

If this capability is requested by the client, the semantics of
"deepen" command is changed. The "depth" argument is the depth from
the current shallow boundary, instead of the depth from remote refs.

no-progress
-----------

Expand Down
24 changes: 21 additions & 3 deletions builtin/clone.c
Expand Up @@ -41,9 +41,11 @@ static const char * const builtin_clone_usage[] = {
static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;
static int option_local = -1, option_no_hardlinks, option_shared, option_recursive;
static int option_shallow_submodules;
static char *option_template, *option_depth;
static int deepen;
static char *option_template, *option_depth, *option_since;
static char *option_origin = NULL;
static char *option_branch = NULL;
static struct string_list option_not = STRING_LIST_INIT_NODUP;
static const char *real_git_dir;
static char *option_upload_pack = "git-upload-pack";
static int option_verbosity;
Expand Down Expand Up @@ -94,6 +96,10 @@ static struct option builtin_clone_options[] = {
N_("path to git-upload-pack on the remote")),
OPT_STRING(0, "depth", &option_depth, N_("depth"),
N_("create a shallow clone of that depth")),
OPT_STRING(0, "shallow-since", &option_since, N_("time"),
N_("create a shallow clone since a specific time")),
OPT_STRING_LIST(0, "shallow-exclude", &option_not, N_("revision"),
N_("deepen history of shallow clone by excluding rev")),
OPT_BOOL(0, "single-branch", &option_single_branch,
N_("clone only one branch, HEAD or --branch")),
OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules,
Expand Down Expand Up @@ -861,8 +867,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
usage_msg_opt(_("You must specify a repository to clone."),
builtin_clone_usage, builtin_clone_options);

if (option_depth || option_since || option_not.nr)
deepen = 1;
if (option_single_branch == -1)
option_single_branch = option_depth ? 1 : 0;
option_single_branch = deepen ? 1 : 0;

if (option_mirror)
option_bare = 1;
Expand Down Expand Up @@ -1006,6 +1014,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (is_local) {
if (option_depth)
warning(_("--depth is ignored in local clones; use file:// instead."));
if (option_since)
warning(_("--shallow-since is ignored in local clones; use file:// instead."));
if (option_not.nr)
warning(_("--shallow-exclude is ignored in local clones; use file:// instead."));
if (!access(mkpath("%s/shallow", path), F_OK)) {
if (option_local > 0)
warning(_("source repository is shallow, ignoring --local"));
Expand All @@ -1024,14 +1036,20 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (option_depth)
transport_set_option(transport, TRANS_OPT_DEPTH,
option_depth);
if (option_since)
transport_set_option(transport, TRANS_OPT_DEEPEN_SINCE,
option_since);
if (option_not.nr)
transport_set_option(transport, TRANS_OPT_DEEPEN_NOT,
(const char *)&option_not);
if (option_single_branch)
transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1");

if (option_upload_pack)
transport_set_option(transport, TRANS_OPT_UPLOADPACK,
option_upload_pack);

if (transport->smart_options && !option_depth)
if (transport->smart_options && !deepen)
transport->smart_options->check_self_contained_and_connected = 1;

refs = transport_get_remote_refs(transport);
Expand Down
27 changes: 21 additions & 6 deletions builtin/fetch-pack.c
Expand Up @@ -51,6 +51,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
struct child_process *conn;
struct fetch_pack_args args;
struct sha1_array shallow = SHA1_ARRAY_INIT;
struct string_list deepen_not = STRING_LIST_INIT_DUP;

packet_trace_identity("fetch-pack");

Expand All @@ -60,12 +61,12 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
for (i = 1; i < argc && *argv[i] == '-'; i++) {
const char *arg = argv[i];

if (starts_with(arg, "--upload-pack=")) {
args.uploadpack = arg + 14;
if (skip_prefix(arg, "--upload-pack=", &arg)) {
args.uploadpack = arg;
continue;
}
if (starts_with(arg, "--exec=")) {
args.uploadpack = arg + 7;
if (skip_prefix(arg, "--exec=", &arg)) {
args.uploadpack = arg;
continue;
}
if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) {
Expand Down Expand Up @@ -101,8 +102,20 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
args.verbose = 1;
continue;
}
if (starts_with(arg, "--depth=")) {
args.depth = strtol(arg + 8, NULL, 0);
if (skip_prefix(arg, "--depth=", &arg)) {
args.depth = strtol(arg, NULL, 0);
continue;
}
if (skip_prefix(arg, "--shallow-since=", &arg)) {
args.deepen_since = xstrdup(arg);
continue;
}
if (skip_prefix(arg, "--shallow-exclude=", &arg)) {
string_list_append(&deepen_not, arg);
continue;
}
if (!strcmp(arg, "--deepen-relative")) {
args.deepen_relative = 1;
continue;
}
if (!strcmp("--no-progress", arg)) {
Expand Down Expand Up @@ -132,6 +145,8 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
}
usage(fetch_pack_usage);
}
if (deepen_not.nr)
args.deepen_not = &deepen_not;

if (i < argc)
dest = argv[i++];
Expand Down
50 changes: 43 additions & 7 deletions builtin/fetch.c
Expand Up @@ -35,13 +35,15 @@ static int fetch_prune_config = -1; /* unspecified */
static int prune = -1; /* unspecified */
#define PRUNE_BY_DEFAULT 0 /* do we prune by default? */

static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity;
static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity, deepen_relative;
static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
static int tags = TAGS_DEFAULT, unshallow, update_shallow;
static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen;
static int max_children = -1;
static enum transport_family family;
static const char *depth;
static const char *deepen_since;
static const char *upload_pack;
static struct string_list deepen_not = STRING_LIST_INIT_NODUP;
static struct strbuf default_rla = STRBUF_INIT;
static struct transport *gtransport;
static struct transport *gsecondary;
Expand Down Expand Up @@ -117,6 +119,12 @@ static struct option builtin_fetch_options[] = {
OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
OPT_STRING(0, "depth", &depth, N_("depth"),
N_("deepen history of shallow clone")),
OPT_STRING(0, "shallow-since", &deepen_since, N_("time"),
N_("deepen history of shallow repository based on time")),
OPT_STRING_LIST(0, "shallow-exclude", &deepen_not, N_("revision"),
N_("deepen history of shallow clone by excluding rev")),
OPT_INTEGER(0, "deepen", &deepen_relative,
N_("deepen history of shallow clone")),
{ OPTION_SET_INT, 0, "unshallow", &unshallow, NULL,
N_("convert to a complete repository"),
PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1 },
Expand Down Expand Up @@ -875,7 +883,7 @@ static int quickfetch(struct ref *ref_map)
* really need to perform. Claiming failure now will ensure
* we perform the network exchange to deepen our history.
*/
if (depth)
if (deepen)
return -1;
opt.quiet = 1;
return check_connected(iterate_ref_map, &rm, &opt);
Expand Down Expand Up @@ -983,7 +991,7 @@ static void set_option(struct transport *transport, const char *name, const char
name, transport->url);
}

static struct transport *prepare_transport(struct remote *remote)
static struct transport *prepare_transport(struct remote *remote, int deepen)
{
struct transport *transport;
transport = transport_get(remote, NULL);
Expand All @@ -995,20 +1003,39 @@ static struct transport *prepare_transport(struct remote *remote)
set_option(transport, TRANS_OPT_KEEP, "yes");
if (depth)
set_option(transport, TRANS_OPT_DEPTH, depth);
if (deepen && deepen_since)
set_option(transport, TRANS_OPT_DEEPEN_SINCE, deepen_since);
if (deepen && deepen_not.nr)
set_option(transport, TRANS_OPT_DEEPEN_NOT,
(const char *)&deepen_not);
if (deepen_relative)
set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, "yes");
if (update_shallow)
set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes");
return transport;
}

static void backfill_tags(struct transport *transport, struct ref *ref_map)
{
if (transport->cannot_reuse) {
gsecondary = prepare_transport(transport->remote);
int cannot_reuse;

/*
* Once we have set TRANS_OPT_DEEPEN_SINCE, we can't unset it
* when remote helper is used (setting it to an empty string
* is not unsetting). We could extend the remote helper
* protocol for that, but for now, just force a new connection
* without deepen-since. Similar story for deepen-not.
*/
cannot_reuse = transport->cannot_reuse ||
deepen_since || deepen_not.nr;
if (cannot_reuse) {
gsecondary = prepare_transport(transport->remote, 0);
transport = gsecondary;
}

transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL);
transport_set_option(transport, TRANS_OPT_DEPTH, "0");
transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL);
fetch_refs(transport, ref_map);

if (gsecondary) {
Expand Down Expand Up @@ -1219,7 +1246,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv)
die(_("No remote repository specified. Please, specify either a URL or a\n"
"remote name from which new revisions should be fetched."));

gtransport = prepare_transport(remote);
gtransport = prepare_transport(remote, 1);

if (prune < 0) {
/* no command line request */
Expand Down Expand Up @@ -1279,6 +1306,13 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix,
builtin_fetch_options, builtin_fetch_usage, 0);

if (deepen_relative) {
if (deepen_relative < 0)
die(_("Negative depth in --deepen is not supported"));
if (depth)
die(_("--deepen and --depth are mutually exclusive"));
depth = xstrfmt("%d", deepen_relative);
}
if (unshallow) {
if (depth)
die(_("--depth and --unshallow cannot be used together"));
Expand All @@ -1291,6 +1325,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
/* no need to be strict, transport_set_option() will validate it again */
if (depth && atoi(depth) < 1)
die(_("depth %s is not a positive number"), depth);
if (depth || deepen_since || deepen_not.nr)
deepen = 1;

if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
if (recurse_submodules_default) {
Expand Down
2 changes: 2 additions & 0 deletions commit.h
Expand Up @@ -267,6 +267,8 @@ extern int for_each_commit_graft(each_commit_graft_fn, void *);
extern int is_repository_shallow(void);
extern struct commit_list *get_shallow_commits(struct object_array *heads,
int depth, int shallow_flag, int not_shallow_flag);
extern struct commit_list *get_shallow_commits_by_rev_list(
int ac, const char **av, int shallow_flag, int not_shallow_flag);
extern void set_alternate_shallow_file(const char *path, int override);
extern int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
const struct sha1_array *extra);
Expand Down

0 comments on commit a460ea4

Please sign in to comment.