merge-recursive: clean up get_renamed_dir_portion()
Dscho noted a few things making this function hard to follow.
Restructure it a bit and add comments to make it easier to follow.  The
restructurings include:
  * There was a special case if-check at the end of the function
    checking whether someone just renamed a file within its original
    directory, meaning that there could be no directory rename involved.
    That check was slightly convoluted; it could be done in a more
    straightforward fashion earlier in the function, and can be done
    more cheaply too (no call to strncmp).
  * The conditions for advancing end_of_old and end_of_new before
    calling strchr were both confusing and unnecessary.  If either
    points at a '/', then they need to be advanced in order to find the
    next '/'.  If either doesn't point at a '/', then advancing them one
    char before calling strchr() doesn't hurt.  So, just rip out the
    if conditions and advance both before calling strchr().
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
			
			
				maint
			
			
		
							parent
							
								
									08da6496b6
								
							
						
					
					
						commit
						d3eebaad5e
					
				|  | @ -1943,8 +1943,8 @@ static void get_renamed_dir_portion(const char *old_path, const char *new_path, | ||||||
| 				    char **old_dir, char **new_dir) | 				    char **old_dir, char **new_dir) | ||||||
| { | { | ||||||
| 	char *end_of_old, *end_of_new; | 	char *end_of_old, *end_of_new; | ||||||
| 	int old_len, new_len; |  | ||||||
|  |  | ||||||
|  | 	/* Default return values: NULL, meaning no rename */ | ||||||
| 	*old_dir = NULL; | 	*old_dir = NULL; | ||||||
| 	*new_dir = NULL; | 	*new_dir = NULL; | ||||||
|  |  | ||||||
|  | @ -1955,43 +1955,55 @@ static void get_renamed_dir_portion(const char *old_path, const char *new_path, | ||||||
| 	 *    "a/b/c/d" was renamed to "a/b/some/thing/else" | 	 *    "a/b/c/d" was renamed to "a/b/some/thing/else" | ||||||
| 	 * so, for this example, this function returns "a/b/c/d" in | 	 * so, for this example, this function returns "a/b/c/d" in | ||||||
| 	 * *old_dir and "a/b/some/thing/else" in *new_dir. | 	 * *old_dir and "a/b/some/thing/else" in *new_dir. | ||||||
| 	 * | 	 */ | ||||||
| 	 * Also, if the basename of the file changed, we don't care.  We |  | ||||||
| 	 * want to know which portion of the directory, if any, changed. | 	/* | ||||||
|  | 	 * If the basename of the file changed, we don't care.  We want | ||||||
|  | 	 * to know which portion of the directory, if any, changed. | ||||||
| 	 */ | 	 */ | ||||||
| 	end_of_old = strrchr(old_path, '/'); | 	end_of_old = strrchr(old_path, '/'); | ||||||
| 	end_of_new = strrchr(new_path, '/'); | 	end_of_new = strrchr(new_path, '/'); | ||||||
|  |  | ||||||
| 	if (end_of_old == NULL || end_of_new == NULL) | 	if (end_of_old == NULL || end_of_new == NULL) | ||||||
| 		return; | 		return; /* We haven't modified *old_dir or *new_dir yet. */ | ||||||
|  |  | ||||||
|  | 	/* Find the first non-matching character traversing backwards */ | ||||||
| 	while (*--end_of_new == *--end_of_old && | 	while (*--end_of_new == *--end_of_old && | ||||||
| 	       end_of_old != old_path && | 	       end_of_old != old_path && | ||||||
| 	       end_of_new != new_path) | 	       end_of_new != new_path) | ||||||
| 		; /* Do nothing; all in the while loop */ | 		; /* Do nothing; all in the while loop */ | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * If both got back to the beginning of their strings, then the | ||||||
|  | 	 * directory didn't change at all, only the basename did. | ||||||
|  | 	 */ | ||||||
|  | 	if (end_of_old == old_path && end_of_new == new_path && | ||||||
|  | 	    *end_of_old == *end_of_new) | ||||||
|  | 		return; /* We haven't modified *old_dir or *new_dir yet. */ | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	 * We've found the first non-matching character in the directory | 	 * We've found the first non-matching character in the directory | ||||||
| 	 * paths.  That means the current directory we were comparing | 	 * paths.  That means the current characters we were looking at | ||||||
| 	 * represents the rename.  Move end_of_old and end_of_new back | 	 * were part of the first non-matching subdir name going back from | ||||||
| 	 * to the full directory name. | 	 * the end of the strings.  Get the whole name by advancing both | ||||||
|  | 	 * end_of_old and end_of_new to the NEXT '/' character.  That will | ||||||
|  | 	 * represent the entire directory rename. | ||||||
|  | 	 * | ||||||
|  | 	 * The reason for the increment is cases like | ||||||
|  | 	 *    a/b/star/foo/whatever.c -> a/b/tar/foo/random.c | ||||||
|  | 	 * After dropping the basename and going back to the first | ||||||
|  | 	 * non-matching character, we're now comparing: | ||||||
|  | 	 *    a/b/s          and         a/b/ | ||||||
|  | 	 * and we want to be comparing: | ||||||
|  | 	 *    a/b/star/      and         a/b/tar/ | ||||||
|  | 	 * but without the pre-increment, the one on the right would stay | ||||||
|  | 	 * a/b/. | ||||||
| 	 */ | 	 */ | ||||||
| 	if (*end_of_old == '/') | 	end_of_old = strchr(++end_of_old, '/'); | ||||||
| 		end_of_old++; | 	end_of_new = strchr(++end_of_new, '/'); | ||||||
| 	if (*end_of_old != '/') |  | ||||||
| 		end_of_new++; |  | ||||||
| 	end_of_old = strchr(end_of_old, '/'); |  | ||||||
| 	end_of_new = strchr(end_of_new, '/'); |  | ||||||
|  |  | ||||||
| 	/* | 	/* Copy the old and new directories into *old_dir and *new_dir. */ | ||||||
| 	 * It may have been the case that old_path and new_path were the same | 	*old_dir = xstrndup(old_path, end_of_old - old_path); | ||||||
| 	 * directory all along.  Don't claim a rename if they're the same. | 	*new_dir = xstrndup(new_path, end_of_new - new_path); | ||||||
| 	 */ |  | ||||||
| 	old_len = end_of_old - old_path; |  | ||||||
| 	new_len = end_of_new - new_path; |  | ||||||
|  |  | ||||||
| 	if (old_len != new_len || strncmp(old_path, new_path, old_len)) { |  | ||||||
| 		*old_dir = xstrndup(old_path, old_len); |  | ||||||
| 		*new_dir = xstrndup(new_path, new_len); |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void remove_hashmap_entries(struct hashmap *dir_renames, | static void remove_hashmap_entries(struct hashmap *dir_renames, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Elijah Newren
						Elijah Newren