Re: [PATCH] cleans up builtin-mv

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On Fri, 18 Aug 2006, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@xxxxxx> writes:
> 
> > What you cleverly did not mention: It was inside a
> >
> > 	if (!bad &&
> > 		(length = strlen(source[i])) >= 0 &&
> > 		!strncmp(destination[i], source[i], length) &&
> > 		(destination[i][length] == 0 || destination[i][length] == '/'))
> >
> > construct. So, we assign the "length" variable only if we have to. And the 
> > ">= 0" trick is a common one. I could have done
> >
> > 		!strncmp(destination[i], source[i], (length = strlen(source[i])))
> >
> > but even I find that ugly.
> 
> I usually side with you but on this I can't.
> 
> There are 2 ways to generate branch instructions in C.
> 
>  - compound statements specifically designed for expressing
>    control structure: if () ... else ..., for (), while (),
>    switch (), etc.
> 
>  - expressions using conditional operators or logical operators
>    that short circuit: ... ? ... : ..., ... && ... || ...
> 
> The latter form may still be readable even with simple side
> effects inside its terms, but "(l = strlen(s)) >= 0" is done
> solely for the side effect, and its computed value does not have
> anything to do with the logical operation &&.
> 
> THIS IS UGLY.  And do not want to live in a world where this
> ugliness is a "common one", as you put it.

Okay. Probably the explanation is: I do not use git-mv myself, but only 
got annoyed enough by a failing t7001 to rewrite it.

> And this avoiding one call to strlen(source[i]) is unnecessary
> even as an optimization -- you end up calling strlen() on it
> later in the code anyway, as David points out.
> 
> I think this part is far easier to read if you did it like this:
>  
> 		length = strlen(source[i]);
> 		if (lstat(source[i], &st) < 0)
> 			bad = "bad source";
> 		else if (!strncmp(destination[i], source[i], length) &&
> 			 (destination[i][length] == 0 ||
> 			  destination[i][length] == '/'))
> 			bad = "can not move directory into itself";
> 
> 		if (S_ISDIR(st.st_mode)) {
> 			...
> 
> Note that the above is an absolute minimum rewrite.  Other
> things I noticed are:
> 
>  - source[i] and destination[i] are referenced all the time; the
>    code would be easer to read if you had something like this
>    upfront:
> 
>                 /* Checking */
>                 for (i = 0; i < count; i++) {
>                         const char *bad = NULL;
> 			const char *src = source[i];
>                         const char *dst = destination[i];
>                         int srclen = strlen(src);
>                         int dstlen = strlen(dst);
> 
>    You might end up not using dstlen in some cases, but I think
>    this would be far easier to read.  Micro-optimizing by saying
>    "this is used only in this branch of this later if()
>    statement but in that case it is always set in that branch of
>    that earlier if() statement" makes unmaintainably confusing
>    code.
> 
>  - I do not think you need "const char *dir, *dest_dir" inside
>    the "source is directory" branch; I would just use src and dst
>    consistently;

These changes would make the source more readable, yes.

>  - You muck with dest_dir by calling add_slash(dest_dir) but
>    call prefix_path() with dst_len you computed earlier;
>    prefix_path() may know what to do, but is this intended?

That is probably a late night oversight.

If noone else is faster, I will do the requested changes tomorrow.

Ciao,
Dscho

-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]