git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Re: [PATCH v3] builtin/clone.c: add --reject-shallow option

From
Llilinchao@oschina.cn <lilinchao@oschina.cn>
Date
Feb 10, 2021, 09:07 UTC
Message-ID
<5c4295e46b7f11eb8acc0024e87935e7@oschina.cn>
In-Reply-To
<026bd8966b1611eb975aa4badb2c2b1190694@pobox.com>

-------------- lilinchao@oschina.cn

Show 11 quoted lines
>"Li Linchao via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
>> From: lilinchao <lilinchao@oschina.cn>
>>
>> In some scenarios, users may want more history than the repository
>> offered for cloning, which mostly to be a shallow repository, can
>> give them.
>
>Sorry, but I find this hard to understand.  Are you saying that most
>of the repositories that users try to clone from are shallow? 
> 
Oh, sorry, it shoud be "which happens to be a shallow repository".
Show 8 quoted lines
>> But users don't know it is a shallow repository until
>> they download it to local, users should have the option to refuse
>> to clone this kind of repository, and may want to exit the process
>> immediately without creating any unnecessary files.
>
>This one on the other hand is easy to understand, but we would
>probably need something like s/But/But because/.
> 
Ok, I will substitute it.
Show 13 quoted lines
>> Althought there is an option '--depth=x' for users to decide how
>> deep history they can fetch, but as the unshallow cloning's depth
>> is INFINITY, we can't know exactly the minimun 'x' value that can
>> satisfy the minimum integrity, so we can't pass 'x' value to --depth,
>> and expect this can obtain a complete history of a repository.
>
>Hmph, that is an interesting point.  This makes me wonder if we can
>achieve the same without adding a new option at the UI level (e.g.
>by allowing "--depth" to take "infinity" and reject cloning if we
>find out that the origin repository is a shallow one).  But we can
>worry about it later once after we get the machinery driven by the
>UI right.
> 

Please let me explain the purpose of this patch in another way: In practice, I may need a filter in clone command to filter out remote shallow repository that may appear. I think a new option like '--reject-shallow', or '--filter-shallow', or something like that, has a clearer purpose for users, they don't have to come up with a specific depth number to achieve the same purpose. A literal filter, or option is just ok, I think.

Show 8 quoted lines
>> In other scenarios, given that we have an API that allow us to import
>> external repository, and then perform various operations on the repo.
>
>Sorry, but I do not understand what you want to say with these two
>lines ("Given that X and Y" needs to be followed by a concluding
>statement, e.g. "Given that we have API to import and operate, we
>can do Z"---you are missing that "we can do Z" part).
> 

Forgive my crappy English :-( What I want to express is "if we have an API to do sth, then do sth".

Show 15 quoted lines
>> diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
>> index 02d9c19cec75..af5a97903a05 100644
>> --- a/Documentation/git-clone.txt
>> +++ b/Documentation/git-clone.txt
>> @@ -15,7 +15,7 @@ SYNOPSIS
>>    [--dissociate] [--separate-git-dir <git dir>]
>>    [--depth <depth>] [--[no-]single-branch] [--no-tags]
>>    [--recurse-submodules[=<pathspec>]] [--[no-]shallow-submodules]
>> -	  [--[no-]remote-submodules] [--jobs <n>] [--sparse]
>> +	  [--[no-]remote-submodules] [--jobs <n>] [--sparse] [--reject-shallow]
>
>Isn't it "--[no-]reject-shallow"?  Offering the negation from the
>command line is essential if "[clone] rejectshallow" configuration
>is allowed to set the default to true.
> 
Ok, that makes sense.
Show 81 quoted lines
>> +--reject-shallow::
>> +	Don't clone a shallow source repository. In some scenarios, clients
>> +	want the cloned repository information to be complete. Otherwise,
>> +	the cloning process should end immediately without creating any files,
>> +	which can save some disk space. This can override `clone.rejectshallow`
>> +	from the configuration:
>> +
>> +	--------------------------------------------------------------------
>> +	$ git -c clone.rejectshallow=false clone --reject-shallow source out
>> +	--------------------------------------------------------------------
>> +
>> +	While there is a way to countermand a configured "I always refuse to
>> +	clone from a shallow repository" with "but let's allow it only this time":
>> +
>> +	----------------------------------------------------------------------
>> +	$ git -c clone.rejectshallow=true clone --no-reject-shallow source out
>> +	----------------------------------------------------------------------
>
>
>This is way too verbose and gives unnecessary details that readers
>already know or do not need to know (e.g. setting configuration from
>the command line and immediately override it from the command line
>is not something end-users would EVER need to do---only test writers
>who develop Git would need it).  Something like
>
>    Fail if the source repository is a shallow repository.  The
>    `clone.rejectShallow` configuration variable can be used to
>    give the default.  
>
>would be sufficient.  All readers ought to know when a configuration
>and command line option exist, the latter can be used to override
>the default former gives, and it is *not* a job for the description
>of an individual option to teach them to such a detail like the
>above does.
> 
>> +static int option_no_shallow = -1;  /* unspecified */
>> +static int config_shallow = -1;    /* unspecified */
>
>Hmph.  I would have expected the usual "prepare a single variable
>and initialize it to the default, read the config to set it, and
>then parse the command line to overwrite it" sequence would suffice
>so it is puzzling why we want two separate variables here.
>
>Let's read on to find out.
>
>> @@ -90,6 +92,8 @@ static struct option builtin_clone_options[] = {
>>  OPT__VERBOSITY(&option_verbosity),
>>  OPT_BOOL(0, "progress", &option_progress,
>>  N_("force progress reporting")),
>> +	OPT_BOOL(0, "reject-shallow", &option_no_shallow,
>> +	N_("don't clone shallow repository")),
>>  OPT_BOOL('n', "no-checkout", &option_no_checkout,
>>  N_("don't create a checkout")),
>>  OPT_BOOL(0, "bare", &option_bare, N_("create a bare repository")),
>> @@ -858,6 +862,9 @@ static int git_clone_config(const char *k, const char *v, void *cb)
>>  free(remote_name);
>>  remote_name = xstrdup(v);
>>  }
>> +	if (!strcmp(k, "clone.rejectshallow")) {
>> +	config_shallow = git_config_bool(k, v);
>> +	}
>>  return git_default_config(k, v, cb);
>>  }
>
>You are adding to git_clone_config(), so instead of setting the
>value to config_shallow, setting the value to the same variable that
>will be used in builtin_clone_options[] array should be sufficient.
>
>cmd_clone() begins like so:
>
>
>	git_config(git_clone_config, NULL);
>	argc = parse_options(...);
>
>which means that single variable (let's call it reject_shallow)
>can (1) stay to be its initial value if no config or option is
>given, (2) if there is config, the git_config() call will cause
>that variable assigned, (3) if there is option, parse_options()
>call will cause that variable assigned, possibly overwriting the
>value taken from the config.
> 
Sorry, you may forget there is a re-read git-config under these lines
(around at line 1160):
    	/*
	 * additional config can be injected with -c, make sure it's included
	 * after init_db, which clears the entire config environment.
	 */
	write_config(&option_config);
	/*
	 * re-read config after init_db and write_config to pick up any config
	 * injected by --template and --config, respectively.
	 */
	git_config(git_clone_config, NULL);

so, what I can think of is introducing a new variable for git_clone_config, and I find that in the other place, "define a new config_xxx variable for git-config" is usual.

Show 62 quoted lines
>Which is exactly what we want.  So in short, declare just a single
>
>    static int reject_shallow; /* default to false */
>   
>instead of "option_no_shallow" and "config_shallow", and use it in
>both builtin_clone_options[] given to parse_options, and
>git_clone_config() that is given to git_config(), and you'd be fine,
>I think.
>
>> @@ -963,6 +970,7 @@ static int path_exists(const char *path)
>>  int cmd_clone(int argc, const char **argv, const char *prefix)
>>  {
>>  int is_bundle = 0, is_local;
>> +	int is_shallow = 0;
>>  const char *repo_name, *repo, *work_tree, *git_dir;
>>  char *path, *dir, *display_repo = NULL;
>>  int dest_exists, real_dest_exists = 0;
>> @@ -1205,6 +1213,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>> 
>>  path = get_repo_path(remote->url[0], &is_bundle);
>>  is_local = option_local != 0 && path && !is_bundle;
>> +
>> +	/* Detect if the remote repository is shallow */
>> +	if (!access(mkpath("%s/shallow", path), F_OK)) {
>> +	is_shallow = 1;
>> +	}
>
>This is only for cloning from a local repository, no?  IOW, path at
>this point may even be "git://github.com/git/git/" and checking with
>access() does not make sense.
>
>Ah, it is even worse.  get_repo_path() can return NULL, so mkpath()
>will crash in such a case.  This must be at least
>
>	if (path && !access(mkpath("%s/shallow", path), F_OK))
>	is_shallow = 1;
>
>but I think the logic fits better in the body of "if (is_Local)"
>thing that immediately follows.  It is specific to the case where
>cloning from a local repository and access(mkpath()) that is about
>the local filesystem (as opposed to going through the transport
>layer) belongs there.
>
>>  if (is_local) {
>>  if (option_depth)
>>  warning(_("--depth is ignored in local clones; use file:// instead."));
>> @@ -1214,7 +1228,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>>  warning(_("--shallow-exclude is ignored in local clones; use file:// instead."));
>>  if (filter_options.choice)
>>  warning(_("--filter is ignored in local clones; use file:// instead."));
>> -	if (!access(mkpath("%s/shallow", path), F_OK)) {
>> +	if (is_shallow) {
>>  if (option_local > 0)
>>  warning(_("source repository is shallow, ignoring --local"));
>>  is_local = 0;
>
>So, I think the above two hunks are making the code worse.  If we
>are to detect and reject cloning from the shallow repository when
>going through the transport layer (i.e. "--no-local" or cloning from
>"git://github.com/git/git", or "https://github.com/git/git", if it
>were a shallow repository), that must be handled separately.
> 

Sorry, I made the question simple. Reject cloning a shallow repository should apply to all four type transport protocols. There still a bunch of work to be done.

Show 39 quoted lines
>> @@ -1222,6 +1236,25 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>>  }
>>  if (option_local > 0 && !is_local)
>>  warning(_("--local is ignored"));
>> +
>> +	if (is_shallow) {
>> +	int reject = 0;
>> +
>> +	/* If option_no_shallow is specified from CLI option,
>> +	* ignore config_shallow from git_clone_config.
>> +	*/
>> +
>> +	if (config_shallow != -1) {
>> +	reject = config_shallow;
>> +	}
>> +	if (option_no_shallow != -1) {
>> +	reject = option_no_shallow;
>> +	}
>
>I do not think any of the above is necessary with just a single
>reject_shallow variable that is initialized to 0, can be set by
>git_config() callback, and can further be set by parse_options().
>
>> +	if (reject) {
>> +	die(_("source repository is shallow, reject to clone."));
>> +	}
>
>> +	}
>> +
>>  transport->cloning = 1;
>> 
>>  transport_set_option(transport, TRANS_OPT_KEEP, "yes");
>
>I do not see how this change would allow users to reject cloning
>http://github.com/git/git, if that repository were shallow, though. 
>I think that would need changes to the code that interacts with
>these transport_* functions we see later part of this functrion.
>
>Thanks. 

On the whole, thank you for all your patience and suggestions! I will dig into the code, and base on your suggestions to figure it out.

Finally, I wish you a Happy Lunar New Year! ^-^
-Lilinchao
Previous: lilinchao@oschina.cnNext: Junio C Hamano
Message 42 of 48 in “builtin/clone.c: add --no-shallow option”
  1. builtin/clone.c: add --no-shallow optionLi Linchao via GitGitGadget, Feb 4, 2021
  2. Junio C HamanoFeb 4, 2021
  3. lilinchao@oschina.cnFeb 4, 2021
  4. Junio C HamanoFeb 4, 2021
  5. Johannes SchindelinFeb 4, 2021
  6. Junio C HamanoFeb 4, 2021
  7. 0/2 builtin/clone.c: add --no-shallow optionLi Linchao via GitGitGadget, Feb 8, 2021
  8. 1/2 builtin/clone.c: add --no-shallow optionlilinchao via GitGitGadget, Feb 8, 2021
  9. 2/2 builtin/clone.c: add --reject-shallow optionlilinchao via GitGitGadget, Feb 8, 2021
  10. Derrick StoleeFeb 8, 2021
  11. builtin/clone.c: add --reject-shallow optionLi Linchao via GitGitGadget, Feb 8, 2021
  12. Junio C HamanoFeb 9, 2021
  13. builtin/clone.c: add --reject-shallow optionLi Linchao via GitGitGadget, Feb 21, 2021
  14. Junio C HamanoFeb 22, 2021
  15. Jonathan TanMar 1, 2021
  16. Junio C HamanoMar 1, 2021
  17. lilinchao@oschina.cnMar 2, 2021
  18. Junio C HamanoMar 3, 2021
  19. Jonathan TanMar 4, 2021
  20. builtin/clone.c: add --reject-shallow optionLi Linchao via GitGitGadget, Feb 28, 2021
  21. lilinchao@oschina.cnMar 1, 2021
  22. Johannes SchindelinMar 1, 2021
  23. lilinchao@oschina.cnMar 4, 2021
  24. Junio C HamanoMar 3, 2021
  25. lilinchao@oschina.cnMar 4, 2021
  26. builtin/clone.c: add --reject-shallow optionLi Linchao via GitGitGadget, Mar 4, 2021
  27. lilinchao@oschina.cnMar 12, 2021
  28. builtin/clone.c: add --reject-shallow optionLi Linchao via GitGitGadget, Mar 25, 2021
  29. Junio C HamanoMar 25, 2021
  30. Junio C HamanoMar 25, 2021
  31. builtin/clone.c: add --reject-shallow optionLi Linchao via GitGitGadget, Mar 29, 2021
  32. Junio C HamanoMar 29, 2021
  33. Johannes SchindelinMar 30, 2021
  34. Junio C HamanoMar 30, 2021
  35. Johannes SchindelinMar 31, 2021
  36. builtin/clone.c: add --reject-shallow optionlilinchao via GitGitGadget, Mar 31, 2021
  37. Junio C HamanoMar 31, 2021
  38. Johannes SchindelinMar 31, 2021
  39. Junio C HamanoMar 31, 2021
  40. builtin/clone.c: add --reject-shallow optionLi Linchao via GitGitGadget, Apr 1, 2021
  41. lilinchao@oschina.cnFeb 8, 2021
  42. lilinchao@oschina.cnFeb 10, 2021
  43. Junio C HamanoFeb 10, 2021
  44. lilinchao@oschina.cnFeb 20, 2021
  45. lilinchao@oschina.cnFeb 28, 2021
  46. lilinchao@oschina.cnMar 26, 2021
  47. lilinchao@oschina.cnMar 26, 2021
  48. lilinchao@oschina.cnMar 31, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.