All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sergey Organov <sorganov@gmail.com>
To: Junio C Hamano <gitster@pobox.com>
Cc: git@vger.kernel.org, "Jean-Noël AVILA" <avila.jn@gmail.com>,
	"Kristoffer Haugsbakk" <code@khaugsbakk.name>
Subject: Re: [PATCH v2] clean: improve -n and -f implementation and documentation
Date: Mon, 04 Mar 2024 21:39:40 +0300	[thread overview]
Message-ID: <87h6hl96z7.fsf@osv.gnss.ru> (raw)
In-Reply-To: <20240303220600.2491792-1-gitster@pobox.com> (Junio C. Hamano's message of "Sun, 3 Mar 2024 14:05:59 -0800")

Junio C Hamano <gitster@pobox.com> writes:

> Sergey Organov <sorganov@gmail.com> writes:
>
>> Changes since v1:
>>
>>  * Fixed style of the if() statement
>>
>>  * Merged two error messages into one
>>
>>  * clean.requireForce description changed accordingly
>
> Excellent.
>
>> diff --git a/builtin/clean.c b/builtin/clean.c
>> index d90766cad3a0..41502dcb0dde 100644
>> --- a/builtin/clean.c
>> +++ b/builtin/clean.c
>> @@ -25,7 +25,7 @@
>>  #include "help.h"
>>  #include "prompt.h"
>>
>> -static int force = -1; /* unset */
>> +static int require_force = -1; /* unset */
>>  static int interactive;
>>  static struct string_list del_list = STRING_LIST_INIT_DUP;
>>  static unsigned int colopts;
>> @@ -128,7 +128,7 @@ static int git_clean_config(const char *var, const char *value,
>>  	}
>>
>>  	if (!strcmp(var, "clean.requireforce")) {
>> -		force = !git_config_bool(var, value);
>> +		require_force = git_config_bool(var, value);
>>  		return 0;
>>  	}
>>
>> @@ -920,7 +920,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
>>  {
>>  	int i, res;
>>  	int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0;
>> -	int ignored_only = 0, config_set = 0, errors = 0, gone = 1;
>> +	int ignored_only = 0, force = 0, errors = 0, gone = 1;
>>  	int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT;
>>  	struct strbuf abs_path = STRBUF_INIT;
>>  	struct dir_struct dir = DIR_INIT;
>> @@ -946,22 +946,17 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
>>  	};
>>
>>  	git_config(git_clean_config, NULL);
>> -	if (force < 0)
>> -		force = 0;
>> -	else
>> -		config_set = 1;
>
> The above changes are a significant improvement.  Instead of a
> single "force" variable whose meaning is fuzzy, we now have
> "require_force" to track the config setting, and "force" to indicate
> the "--force" option.  THis makes the code's intent much clearer.
>
>>  	argc = parse_options(argc, argv, prefix, options, builtin_clean_usage,
>>  			     0);
>>
>> -	if (!interactive && !dry_run && !force) {
>> -		if (config_set)
>> -			die(_("clean.requireForce set to true and neither -i, -n, nor -f given; "
>> -				  "refusing to clean"));
>> -		else
>> -			die(_("clean.requireForce defaults to true and neither -i, -n, nor -f given;"
>
> And thanks to that, the above trick with an extra variable "config_set",
> which smells highly a round-about way, can be simplified.
>
>> +	/* Dry run won't remove anything, so requiring force makes no sense */
>> +	if (dry_run)
>> +		require_force = 0;
>> +	if (require_force != 0 && !force && !interactive)
>
> However, the above logic could be improved.  The behaviour we have,
> for a user who does *not* explicitly disable config.requireForce,
> is, that when clean.requireForce is not set to 0, we would fail
> unless one of these is in effect: -f, -n, -i.  Even though using
> either -n or -i makes it unnecessary to use -f *exactly* the same
> way, the above treats dry_run and interactive separately with two if
> statements, which is suboptimal as a "code/logic clean-up".

I wonder do you mean:

	/* Dry run won't remove anything, so requiring force makes no
	* sense. Interactive has its own means of protection, so don't
	* require force as well */
	if (dry_run || interactive)
		require_force = 0;

	if (require_force != 0 && !force)
                die_();

that looks fine to me, as it puts 'force' flag and corresponding
configuration into one if(), whereas both exceptions are put into
another. OTOH, having:

     if (require_force != 0 && !force && !interactive && !dry_run)
                die_();

mixture looks less appealing to me, though I won't fight against it
either.

>
> The reason for the behaviour can be explained this way:
>
>  * "git clean" (with neither -i nor -n.  The user wants the default
>    mode that has no built-in protection will be stopped without -f.
>
>  * "git clean -n".  The user wants the dry-run mode that has its own
>    protection, i.e. being always no-op to the files, so there is no
>    need to fail here for the lack of "-f".
>
>  * "git clean --interactive".  The user wants the interactive mode
>    that has its own protection, i.e. giving the end-user a chance to
>    say "oh, I didn't mean to remove these files, 'q'uit from this
>    mistake", so there is no need to fail here for the lack of "-f".

Well, if we remove -i from error message as well, then yes, this makes
sense.

>
>> +		die(_("clean.requireForce is true and neither -f nor -i given:"
>>  				  " refusing to clean"));
>
> The message is certainly cleaner compared to the previous round, but
> this also can be improved.  Stepping back a bit and thinking who are
> the target audience of this message.  The only users who see this
> message are running "git clean" in its default (unprotected) mode,
> and they wanted to "clean" for real.  If they wanted to do dry-run,
> they would have said "-n" themselves, and that is why we can safely
> omit mention of "-n" we had in the original message.
>
> These users did not want to run the interractive clean, either---if
> they wanted to go interractive, they would have said "-i"
> themselves.  So we do not need to mention "-i" either for exactly
> the same logic.

I then suggest to consider to remove mention of -i from
clean.requireForce description as well.

>
> Based on the above observation,
>
> I'll send a follow-up patch to clean up the code around here (both
> implementation and documentation), taking '-i' into account as well.

Fine, thanks!

-- Sergey Organov

  parent reply	other threads:[~2024-03-04 18:39 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <7le6ziqzb.fsf_-_@osv.gnss.ru>
2024-03-03 22:05 ` [PATCH v2] clean: improve -n and -f implementation and documentation Junio C Hamano
2024-03-03 22:06   ` [PATCH 1/1] clean: further clean-up of implementation around "--force" Junio C Hamano
2024-03-03 22:18     ` Junio C Hamano
2024-03-04 18:46     ` Sergey Organov
2024-03-04 18:39   ` Sergey Organov [this message]
2024-03-04 18:41     ` [PATCH v2] clean: improve -n and -f implementation and documentation Junio C Hamano
2024-03-04 18:48       ` Sergey Organov
2024-03-04 19:03     ` Junio C Hamano
2024-03-04 20:19       ` Sergey Organov
2024-01-09 20:20 what should "git clean -n -f [-d] [-x] <pattern>" do? Junio C Hamano
2024-02-29 19:07 ` [PATCH] clean: improve -n and -f implementation and documentation Sergey Organov
2024-03-03  9:50   ` [PATCH v2] " Sergey Organov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87h6hl96z7.fsf@osv.gnss.ru \
    --to=sorganov@gmail.com \
    --cc=avila.jn@gmail.com \
    --cc=code@khaugsbakk.name \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.