Thread (1 message) 1 message, 1 author, 2016-06-15

Re: [ANNOUNCE] git-pasky-0.7

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:41:54

I was reviewing the differences in C-part between what is in
git-pasky and Linus tree.  By the way, I finally decided to look
at the upper layer again, now you switched to dircache based
implementation.  It looks like a good start.  Anyway, this
message is about purely C part.

First some nitpicks and possible bugs.

 - The remove_file_from_cache() function in read-cache.c was
   fixed for quite some time ago in the Linus tree to let users
   resolve unmerged path by "update-cache --remove".  You do not
   seem to have this part (the diff is reversed) [*R1*].  If this is
   not a merge oversight I'd like to know why?

 - show-diff exiting non-zero when unmatched paths are specified
   does not make much sense.  diff traditionally exits non-zero
   when differences are found.  Are you using this exit status
   to see if entries on the command line are in the dircache?
   If so that is not show-diff's job but probably belongs to
   show-files [*R2*].

Comments, commends and requests.

 - The -t option you have in show-files sounds generally
   useful [*R3*].  Could you push this upstream?

 - There are many small changes that adds free() and close(fd)
   and from my cursory looking they all look reasonable fixes.
   If you are confident with these, could please also push them
   upstream?

Thanks.

[References]

*R1*

This hunk should be reverted from Pasky if there is no good reason.
--- git.linus/read-cache.c	2005-04-24 00:05:02.000000000 -0700
+++ git.pasky/read-cache.c	2005-04-24 00:49:00.000000000 -0700
@@ -99,9 +99,7 @@
 int remove_file_from_cache(char *path)
 {
 	int pos = cache_name_pos(path, strlen(path));
-	if (pos < 0)
-		pos = -pos-1;
-	while (pos < active_nr && !strcmp(active_cache[pos]->name, path))
+	if (pos >= 0)
 		remove_entry_at(pos);
 	return 0;
 }
*R2*

This hunk should be reverted from Pasky if there is no good reason.
--- git.linus/show-diff.c	2005-04-24 00:05:02.000000000 -0700
+++ git.pasky/show-diff.c	2005-04-24 00:49:00.000000000 -0700
@@ -126,6 +127,7 @@
 	int machine_readable = 0;
 	int reverse = 0;
 	int entries = read_cache();
+	int matched = 0;
 	int i;
 
 	while (1 < argc && argv[1][0] == '-') {
@@ -161,6 +163,7 @@
 		if (1 < argc &&
 		    ! matches_pathspec(ce, argv+1, argc-1))
 			continue;
+		matched++;
 
 		if (ce_stage(ce)) {
 			if (machine_readable)
@@ -192,10 +195,8 @@
 			continue;
 		if (!machine_readable)
 			printf("%s: %s\n", ce->name, sha1_to_hex(ce->sha1));
-		else {
-			printf("%s %s%c", sha1_to_hex(ce->sha1), ce->name, 0);
-			continue;
-		}
+		else
+			printf("M %s %s%c", sha1_to_hex(ce->sha1), ce->name, 0);
 		if (silent)
 			continue;
 
@@ -208,5 +209,8 @@
 					 reverse);
 		free(old);
 	}
+
+	if (1 < argc && !matched)
+		return 1;
 	return 0;
 }
*R3*

This should be pushed upstream.
--- git.linus/show-files.c	2005-04-24 00:05:02.000000000 -0700
+++ git.pasky/show-files.c	2005-04-24 00:49:00.000000000 -0700
@@ -17,6 +17,11 @@
 static int show_unmerged = 0;
 static int line_terminator = '\n';
 
+static const char *tag_cached = "";
+static const char *tag_unmerged = "";
+static const char *tag_removed = "";
+static const char *tag_other = "";
+
 static const char **dir;
 static int nr_dir;
 static int dir_alloc;
@@ -107,7 +112,7 @@
 	}
 	if (show_others) {
 		for (i = 0; i < nr_dir; i++)
-			printf("%s%c", dir[i], line_terminator);
+			printf("%s%s%c", tag_other, dir[i], line_terminator);
 	}
 	if (show_cached | show_stage) {
 		for (i = 0; i < active_nr; i++) {
@@ -115,10 +120,13 @@
 			if (show_unmerged && !ce_stage(ce))
 				continue;
 			if (!show_stage)
-				printf("%s%c", ce->name, line_terminator);
+				printf("%s%s%c",
+				       ce_stage(ce) ? tag_unmerged : tag_cached,
+				       ce->name, line_terminator);
 			else
 				printf(/* "%06o %s %d %10d %s%c", */
-				       "%06o %s %d %s%c",
+				       "%s %06o %s %d %s%c",
+				       ce_stage(ce) ? tag_unmerged : tag_cached,
 				       ntohl(ce->ce_mode),
 				       sha1_to_hex(ce->sha1),
 				       ce_stage(ce),
@@ -132,7 +140,7 @@
 			struct stat st;
 			if (!stat(ce->name, &st))
 				continue;
-			printf("%s%c", ce->name, line_terminator);
+			printf("%s%s%c", tag_removed, ce->name, line_terminator);
 		}
 	}
 	if (show_ignored) {
@@ -151,6 +159,13 @@
 			line_terminator = 0;
 			continue;
 		}
+		if (!strcmp(arg, "-t")) {
+			tag_cached = "H ";
+			tag_unmerged = "M ";
+			tag_removed = "R ";
+			tag_other = "? ";
+			continue;
+		}
 
 		if (!strcmp(arg, "--cached")) {
 			show_cached = 1;
@@ -179,7 +194,7 @@
 			continue;
 		}
 
-		usage("show-files [-z] (--[cached|deleted|others|ignored|stage])*");
+		usage("show-files [-z] [-t] (--[cached|deleted|others|ignored|stage])*");
 	}
 
 	/* With no flags, we default to showing the cached files */

*R4*

These leak fixes look reasonable from cursory looking.  If you
are confident, please push them upstream.
--- git.linus/checkout-cache.c	2005-04-24 00:05:02.000000000 -0700
+++ git.pasky/checkout-cache.c	2005-04-24 00:49:00.000000000 -0700
@@ -48,6 +48,7 @@
 		buf[len] = 0;
 		mkdir(buf, 0755);
 	}
+	free(buf);
 }
 
 static int create_file(const char *path, unsigned int mode)
@@ -75,6 +76,8 @@
 
 	new = read_sha1_file(ce->sha1, type, &size);
 	if (!new || strcmp(type, "blob")) {
+		if (new)
+			free(new);
 		return error("checkout-cache: unable to read sha1 file of %s (%s)",
 			path, sha1_to_hex(ce->sha1));
 	}


--- git.linus/ls-tree.c	2005-04-24 00:05:02.000000000 -0700
+++ git.pasky/ls-tree.c	2005-04-24 00:49:00.000000000 -0700
@@ -77,6 +77,7 @@
 	if (!buffer)
 		die("unable to read sha1 file");
 	list_recursive(buffer, "tree", size, NULL);
+	free(buffer);
 	return 0;
 }
 

--- git.linus/read-tree.c	2005-04-24 00:05:02.000000000 -0700
+++ git.pasky/read-tree.c	2005-04-24 00:49:00.000000000 -0700
@@ -11,11 +11,14 @@
 {
 	void *buffer;
 	unsigned long size;
+	int ret;
 
 	buffer = read_tree_with_tree_or_commit_sha1(sha1, &size, 0);
 	if (!buffer)
 		return -1;
-	return read_tree(buffer, size, stage);
+	ret = read_tree(buffer, size, stage);
+	free(buffer);
+	return ret;
 }
 
 static char *lockfile_name;


--- git.linus/rev-tree.c	2005-04-24 00:05:02.000000000 -0700
+++ git.pasky/rev-tree.c	2005-04-24 00:49:00.000000000 -0700
@@ -56,10 +56,10 @@
 	struct commit_list *parents;
 	struct commit *obj = lookup_commit(sha1);
 
-	if (obj->object.parsed)
+	if (obj && obj->object.parsed)
 		return;
-
-	parse_commit(obj);
+	if (!obj || parse_commit(obj))
+		die("unable to parse commit (%s)", sha1_to_hex(sha1));
 	
 	parents = obj->parents;
 	while (parents) {


--- git.linus/show-diff.c	2005-04-24 00:05:02.000000000 -0700
+++ git.pasky/show-diff.c	2005-04-24 00:49:00.000000000 -0700
@@ -100,6 +100,7 @@
 		return;
 	}
 	show_differences("/dev/null", ce->name, old, size, reverse);
+	free(old);
 }
 
 static const char *show_diff_usage = "show-diff [-q] [-s] [-z] [paths...]";

* These all look genuine leak fixes.  If applicable to Linus tree please
  push them upstream.
--- git.linus/checkout-cache.c	2005-04-24 00:05:02.000000000 -0700
+++ git.pasky/checkout-cache.c	2005-04-24 00:49:00.000000000 -0700
@@ -48,6 +48,7 @@
 		buf[len] = 0;
 		mkdir(buf, 0755);
 	}
+	free(buf);
 }
 
 static int create_file(const char *path, unsigned int mode)
@@ -75,6 +76,8 @@
 
 	new = read_sha1_file(ce->sha1, type, &size);
 	if (!new || strcmp(type, "blob")) {
+		if (new)
+			free(new);
 		return error("checkout-cache: unable to read sha1 file of %s (%s)",
 			path, sha1_to_hex(ce->sha1));
 	}


--- git.linus/ls-tree.c	2005-04-24 00:05:02.000000000 -0700
+++ git.pasky/ls-tree.c	2005-04-24 00:49:00.000000000 -0700
@@ -77,6 +77,7 @@
 	if (!buffer)
 		die("unable to read sha1 file");
 	list_recursive(buffer, "tree", size, NULL);
+	free(buffer);
 	return 0;
 }
 
--- git.linus/read-tree.c	2005-04-24 00:05:02.000000000 -0700
+++ git.pasky/read-tree.c	2005-04-24 00:49:00.000000000 -0700
@@ -11,11 +11,14 @@
 {
 	void *buffer;
 	unsigned long size;
+	int ret;
 
 	buffer = read_tree_with_tree_or_commit_sha1(sha1, &size, 0);
 	if (!buffer)
 		return -1;
-	return read_tree(buffer, size, stage);
+	ret = read_tree(buffer, size, stage);
+	free(buffer);
+	return ret;
 }
 
 static char *lockfile_name;

--- git.linus/rev-tree.c	2005-04-24 00:05:02.000000000 -0700
+++ git.pasky/rev-tree.c	2005-04-24 00:49:00.000000000 -0700
@@ -56,10 +56,10 @@
 	struct commit_list *parents;
 	struct commit *obj = lookup_commit(sha1);
 
-	if (obj->object.parsed)
+	if (obj && obj->object.parsed)
 		return;
-
-	parse_commit(obj);
+	if (!obj || parse_commit(obj))
+		die("unable to parse commit (%s)", sha1_to_hex(sha1));
 	
 	parents = obj->parents;
 	while (parents) {

--- git.linus/sha1_file.c	2005-04-24 00:05:02.000000000 -0700
+++ git.pasky/sha1_file.c	2005-04-24 00:49:00.000000000 -0700
@@ -278,6 +278,7 @@
 
 	if (write(fd, compressed, size) != size)
 		die("unable to write file");
+	free(compressed);
 	close(fd);
 		
 	return 0;
@@ -295,8 +296,10 @@
 	if (fd < 0)
 		return -1;
 
-	if (fstat(fd, &st) < 0 || size != st.st_size)
+	if (fstat(fd, &st) < 0 || size != st.st_size) {
+		close(fd);
 		return -1;
+	}
 
 	map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
 	close(fd);


--- git.linus/show-diff.c	2005-04-24 00:05:02.000000000 -0700
+++ git.pasky/show-diff.c	2005-04-24 00:49:00.000000000 -0700
@@ -100,6 +100,7 @@
 		return;
 	}
 	show_differences("/dev/null", ce->name, old, size, reverse);
+	free(old);
 }
 
 static const char *show_diff_usage = "show-diff [-q] [-s] [-z] [paths...]";


--- git.linus/update-cache.c	2005-04-24 00:05:02.000000000 -0700
+++ git.pasky/update-cache.c	2005-04-24 00:49:00.000000000 -0700
@@ -104,6 +104,11 @@
 		close(fd);
 		return -1;
 	}
+	if (S_ISDIR(st.st_mode)) {
+		fprintf(stderr, "'%s' is a directory, ignoring\n", path);
+		close(fd);
+		return 0;
+	}
 	namelen = strlen(path);
 	size = cache_entry_size(namelen);
 	ce = malloc(size);
@@ -113,10 +118,15 @@
 	ce->ce_mode = create_ce_mode(st.st_mode);
 	ce->ce_flags = htons(namelen);
 
-	if (index_fd(ce->sha1, fd, &st) < 0)
+	if (index_fd(ce->sha1, fd, &st) < 0) {
+		free(ce);
 		return -1;
-
-	return add_cache_entry(ce, allow_add);
+	}
+	if (add_cache_entry(ce, allow_add)) {
+		free(ce);
+		return -1;
+	}
+	return 0;
 }
 
 static int match_data(int fd, void *buffer, unsigned long size)
@@ -141,7 +151,7 @@
 	if (fd >= 0) {
 		void *buffer;
 		unsigned long size;
-		char type[10];
+		char type[20];
 
 		buffer = read_sha1_file(ce->sha1, type, &size);
 		if (buffer) {
@@ -216,6 +226,9 @@
 			printf("%s: needs update\n", ce->name);
 			continue;
 		}
+		/* You can NOT just free active_cache[i] here, since it
+		 * might not be necessarily malloc()ed but can also come
+		 * from mmap(). */
 		active_cache[i] = new;
 	}
 }
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help