Recently I have done some modification - added option --update-file to
gtags. It updates tags for single file. I have seen that someone on
the list, also requested this feature. Possibility of considering
single file during tags update, is essential for me. I am using file
system mounted via network, with source files spread among the other
files. Tags creation sometimes takes hours - traversing through the
filesystem is very slow. Now I can do tags update after single file
edit.
Its a clean pleasure to use emacs with gnu global :-)

Attached diff, contains this feature, together with changes I did
before (IGNORE_ERROR flag and fixed root dir recognition on win32).

Regards
Mikolaj Sitarz
diff -ru global-5.7.5/gtags/const.h global-5.7.5c/gtags/const.h
--- global-5.7.5/gtags/const.h	2009-03-14 01:30:38.000000000 +0100
+++ global-5.7.5c/gtags/const.h	2009-08-06 19:09:33.000000000 +0200
@@ -26,6 +26,9 @@
 -i, --incremental\n\
        Update tag files incrementally. You had better use\n\
        global(1) with the -u option.\n\
+--update-file file\n\
+       Update tag files for single file. Can not be used\n\
+       together with -i option.\n\
 -n, --max-args number\n\
        Maximum number of arguments for gtags-parser(1).\n\
        By default, gtags invokes gtags-parser with arguments\n\
diff -ru global-5.7.5/gtags/gtags.c global-5.7.5c/gtags/gtags.c
--- global-5.7.5/gtags/gtags.c	2009-03-14 01:30:37.000000000 +0100
+++ global-5.7.5c/gtags/gtags.c	2009-08-06 21:46:33.000000000 +0200
@@ -79,6 +79,7 @@
 int debug;
 const char *config_name;
 const char *file_list;
+const char *update_file;
 
 /*
  * Path filter
@@ -136,10 +137,12 @@
 #define OPT_GTAGSCONF		129
 #define OPT_GTAGSLABEL		130
 #define OPT_PATH		131
+#define OPT_UPDATE_FILE         132
 	{"config", optional_argument, NULL, OPT_CONFIG},
 	{"gtagsconf", required_argument, NULL, OPT_GTAGSCONF},
 	{"gtagslabel", required_argument, NULL, OPT_GTAGSLABEL},
 	{"path", required_argument, NULL, OPT_PATH},
+	{"update-file",required_argument, NULL, OPT_UPDATE_FILE},
 	{ 0 }
 };
 
@@ -189,6 +192,9 @@
 			else
 				die("Unknown path type.");
 			break;
+		case OPT_UPDATE_FILE:
+			update_file = optarg;
+			break;
 		case 'c':
 			cflag++;
 			break;
@@ -230,6 +236,11 @@
 			break;
 		}
 	}
+
+	if (iflag && update_file) {
+		die("options: -i and --update-file can not be used together");
+	}
+
 	if (gtagsconf) {
 		char path[MAXPATHLEN+1];
 
@@ -306,6 +317,19 @@
 		else if (!test("r", file_list))
 			die("'%s' is not readable.", file_list);
 	}
+
+	/*
+	 * the same checking for update_file 
+	 */
+	if(update_file) {
+		if (test("d", update_file))
+			die("'%s' is a directory.", update_file);
+		else if (!test("f", update_file))
+			die("'%s' not found.", update_file);
+		else if (!test("r", update_file))
+			die("'%s' is not readable.", update_file);	
+	}
+
 	if (!getcwd(cwd, MAXPATHLEN))
 		die("cannot get current directory.");
 	canonpath(cwd);
@@ -318,7 +342,7 @@
 	 * at one of the candedite directories then gtags use existing
 	 * tag files.
 	 */
-	if (iflag) {
+	if (iflag || update_file) {
 		if (argc > 0)
 			realpath(*argv, dbpath);
 		else if (!gtagsexist(cwd, dbpath, MAXPATHLEN, vflag))
@@ -341,6 +365,12 @@
 			warning("GTAGS or GPATH not found. -i option ignored.");
 		iflag = 0;
 	}
+	if (update_file && (!test("f", makepath(dbpath, dbname(GTAGS), NULL)) ||
+		!test("f", makepath(dbpath, dbname(GPATH), NULL)))) {
+		if (wflag)
+			warning("GTAGS or GPATH not found. --update-file option ignored.");
+		update_file = 0;
+	}
 	if (!test("d", dbpath))
 		die("directory '%s' not found.", dbpath);
 	if (vflag)
@@ -368,9 +398,9 @@
 	if (wflag)
 		set_env("GTAGSWARNING", "1");
 	/*
-	 * incremental update.
+	 * incremental or single file update.
 	 */
-	if (iflag) {
+	if (iflag || update_file) {
 		/*
 		 * Version check. If existing tag files are old enough
 		 * gtagsopen() abort with error message.
@@ -501,6 +531,8 @@
 	 */
 	if (file_list)
 		find_open_filelist(file_list, root);
+	else if (update_file)
+		find_open_single_file(update_file,root);
 	else
 		find_open(NULL);
 	total = 0;
@@ -540,8 +572,9 @@
 	/*
 	 * make delete list.
 	 */
+
 	limit = gpath_nextkey();
-	for (id = 1; id < limit; id++) {
+	for (id = 1; id < limit && !update_file; id++) {
 		char fid[32];
 		int type;
 
diff -ru global-5.7.5/libutil/find.c global-5.7.5c/libutil/find.c
--- global-5.7.5/libutil/find.c	2009-03-14 01:30:37.000000000 +0100
+++ global-5.7.5c/libutil/find.c	2009-08-06 19:09:33.000000000 +0200
@@ -81,12 +81,14 @@
 static char **listarray;		/* list for skipping full path */
 static FILE *ip;
 static FILE *temp;
+static const char *update_file;
 static char rootdir[MAXPATHLEN+1];
 static char cwddir[MAXPATHLEN+1];
 static int find_mode;
 static int find_eof;
 #define FIND_OPEN	1
 #define FILELIST_OPEN	2
+#define SINGLE_FILE_OPEN 3
 
 static void trim(char *);
 static char *find_read_traverse(void);
@@ -475,7 +477,11 @@
 	/*
 	 * rootdir always ends with '/'.
 	 */
+#if defined(_WIN32) || defined(__DJGPP__)
+	if (!strcmp(root+2, "/"))
+#else
 	if (!strcmp(root, "/"))
+#endif
 		strlimcpy(rootdir, root, sizeof(rootdir));
 	else
 		snprintf(rootdir, sizeof(rootdir), "%s/", root);
@@ -486,6 +492,27 @@
 	prepare_skip();
 	prepare_source();
 }
+
+void find_open_single_file(const char *filename, const char *root) {
+	assert(find_mode == 0);
+	find_mode = SINGLE_FILE_OPEN;
+
+	update_file = filename;
+	
+	/*
+	 * rootdir always ends with '/'.
+	 */
+#if defined(_WIN32) || defined(__DJGPP__)
+	if (!strcmp(root+2, "/"))
+#else
+	if (!strcmp(root, "/"))
+#endif
+		strlimcpy(rootdir, root, sizeof(rootdir));
+	else
+		snprintf(rootdir, sizeof(rootdir), "%s/", root);
+	strlimcpy(cwddir, root, sizeof(cwddir));
+}
+
 /*
  * find_read: read path without GPATH.
  *
@@ -503,6 +530,8 @@
 		path = find_read_filelist();
 	else if (find_mode == FIND_OPEN)
 		path = find_read_traverse();
+	else if (find_mode == SINGLE_FILE_OPEN)
+		path = find_read_filelist(); 
 	else
 		die("find_read: internal error.");
 	return path;
@@ -621,7 +650,12 @@
 
 	strbuf_clear(ib);
 	for (;;) {
-		path = strbuf_fgets(ib, ip, STRBUF_NOCRLF);
+		if(find_mode != SINGLE_FILE_OPEN)
+			path = strbuf_fgets(ib, ip, STRBUF_NOCRLF);
+		else {
+			path = (char *) update_file;
+			update_file = 0;
+		}
 		if (path == NULL) {
 			/* EOF */
 			find_eof = 1;
@@ -674,6 +708,7 @@
 		return path;
 	}
 }
+
 /*
  * find_close: close iterator.
  */
@@ -691,9 +726,11 @@
 		 */
 		if (ip != temp)
 			fclose(ip);
-	} else {
+	} else if (find_mode == SINGLE_FILE_OPEN) {
+		/* nothing to close now */ } 
+	else
 		die("find_close: internal error.");
-	}
+	
 	regfree(suff);
 	if (skip)
 		regfree(skip);
diff -ru global-5.7.5/libutil/getdbpath.c global-5.7.5c/libutil/getdbpath.c
--- global-5.7.5/libutil/getdbpath.c	2009-03-14 01:30:37.000000000 +0100
+++ global-5.7.5c/libutil/getdbpath.c	2009-08-06 19:09:13.000000000 +0200
@@ -305,7 +305,11 @@
 			break;
 		} while (0);
 	}
+#if defined(_WIN32) || defined(__DJGPP__)
+	if (!strcmp(root+2, "/"))
+#else
 	if (!strcmp(root, "/"))
+#endif
 		strlimcpy(root_with_slash, root, sizeof(root_with_slash));
 	else
 		snprintf(root_with_slash, sizeof(root_with_slash), "%s/", root);
diff -ru global-5.7.5/libutil/xargs.c global-5.7.5c/libutil/xargs.c
--- global-5.7.5/libutil/xargs.c	2009-03-14 01:30:37.000000000 +0100
+++ global-5.7.5c/libutil/xargs.c	2009-08-06 19:09:13.000000000 +0200
@@ -283,7 +283,12 @@
 	 * was not found. If you would like to use such command, set the
 	 * flag to 1.
 	 */
+#ifdef IGNORE_ERROR
+	xp->ignore_error = 1;
+#else
 	xp->ignore_error = 0;
+#endif
+
 	/*
 	 * By default, we doesn't put the path to GPATH.
 	 * This option is prepared for createtags() and updatetags().
_______________________________________________
Bug-global mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-global

Reply via email to