bug-global
[Top][All Lists]
Advanced

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

Following Symbolic Links


From: Leo L. Schwab
Subject: Following Symbolic Links
Date: Mon, 18 Jan 2010 17:43:08 -0800
User-agent: Mutt/1.5.20 (2009-06-14)

        I posted this patch about six months ago, receiving one favorable
response.  I'm reposting it, updated for global v5.7.7.

        This patch adds a new argument to gtags: --follow-links.  This
allows the user to control how gtags will follow symbolic links -- follow
only links to files, only links to directories, links to both, or follow no
links at all.  The default behavior of gtags (follow all links) is not
changed.

        This patch is offered freely without encumbrance.

        The patch has received only modest testing, but has worked well so
far.  At the very least it can serve as a jumping-off point for discussion.
Let me know what you think.

                                        Thanks,
                                        Schwab
----
diff -ur --exclude='*.o' global-5.7.7/doc/global.info 
global-5.7.7-hacking/doc/global.info
--- global-5.7.7/doc/global.info        2009-12-19 02:50:04.000000000 -0800
+++ global-5.7.7-hacking/doc/global.info        2010-01-18 13:45:12.000000000 
-0800
@@ -2042,7 +2042,7 @@
 
 
 
-     gtags [-ciIOqvw][-d tag-file][-f file][-n number][dbpath]
+     gtags [-ciIOqvw][-d tag-file][-f file][-n number][-l arg][dbpath]
 
 DESCRIPTION
 -----------
@@ -2099,6 +2099,14 @@
      Update tag files incrementally. You had better use global(1) with
      the -u option.
 
+`-l', `--follow-links' dirs|files|both|none
+     Control how symbolic links are followed.  By default, gtags will
+     follow all symbolic links.  Depending on how your source tree is
+     arranged, this may not be desirable.  The argument dirs will cause
+     gtags to only follow symbolic links that point to directories,
+     files will only follow links to files, both will follow all links,
+     and none will ignore all symbolic links.
+
 `-n', `--max-args' number
      Maximum number of arguments for gtags-parser(1).  By default,
      gtags invokes gtags-parser with arguments as many as possible to
@@ -3774,10 +3782,10 @@
 * -r <2>:                                Plug-in.             (line  28)
 * -r <3>:                                Usage(Vim).          (line  44)
 * -r:                                    Usage(Elvis).        (line  13)
-* -s <1>:                                Usage(Elvis).        (line  17)
-* -s <2>:                                Usage(Vim).          (line  48)
-* -s <3>:                                Plug-in.             (line  28)
-* -s:                                    Basic usage.         (line  97)
+* -s <1>:                                Basic usage.         (line  97)
+* -s <2>:                                Usage(Elvis).        (line  17)
+* -s <3>:                                Usage(Vim).          (line  48)
+* -s:                                    Plug-in.             (line  28)
 * -t:                                    Preparation(Elvis).  (line   9)
 * -u:                                    Incremental updating.
                                                               (line   7)
@@ -3832,15 +3840,15 @@
 Node: Reference54586
 Node: global55168
 Node: gtags62679
-Node: htags69891
-Node: gtags-parser82159
-Node: gozilla85659
-Node: gtags-cscope88661
-Node: Copying This Manual91166
-Node: GNU Free Documentation License91412
-Node: Business Model113822
-Node: The BOKIN Model Definition114117
-Node: Frequently Asked Questions118315
-Node: Index121728
+Node: htags70342
+Node: gtags-parser82610
+Node: gozilla86110
+Node: gtags-cscope89112
+Node: Copying This Manual91617
+Node: GNU Free Documentation License91863
+Node: Business Model114273
+Node: The BOKIN Model Definition114568
+Node: Frequently Asked Questions118766
+Node: Index122179
 
 End Tag Table
diff -ur --exclude='*.o' global-5.7.7/doc/gtags.ref 
global-5.7.7-hacking/doc/gtags.ref
--- global-5.7.7/doc/gtags.ref  2009-12-19 02:49:28.000000000 -0800
+++ global-5.7.7-hacking/doc/gtags.ref  2010-01-18 13:44:45.000000000 -0800
@@ -4,7 +4,7 @@
 @unnumberedsubsec SYNOPSIS
 @noindent
 @quotation
-gtags [-ciIOqvw][-d tag-file][-f file][-n address@hidden
+gtags [-ciIOqvw][-d tag-file][-f file][-n number][-l address@hidden
 @end quotation
 @unnumberedsubsec DESCRIPTION
 Gtags recursively collect the source files under
@@ -55,6 +55,14 @@
 @item @samp{-i}, @samp{--incremental}
 Update tag files incrementally. You had better use
 global(1) with the -u option.
address@hidden @samp{-l}, @samp{--follow-links} dirs|files|both|none
+Control how symbolic links are followed.
+By default, gtags will follow all symbolic links.  Depending on
+how your source tree is arranged, this may not be desirable.
+The argument dirs will cause gtags to only follow symbolic
+links that point to directories, files will only follow
+links to files, both will follow all links, and none
+will ignore all symbolic links.
 @item @samp{-n}, @samp{--max-args} number
 Maximum number of arguments for gtags-parser(1).
 By default, gtags invokes gtags-parser with arguments
diff -ur --exclude='*.o' global-5.7.7/gtags/const.h 
global-5.7.7-hacking/gtags/const.h
--- global-5.7.7/gtags/const.h  2009-12-19 02:49:28.000000000 -0800
+++ global-5.7.7-hacking/gtags/const.h  2010-01-18 13:44:45.000000000 -0800
@@ -1,6 +1,6 @@
 /* This file is generated automatically by convert.pl from gtags/manual.in. */
 const char *progname = "gtags";
-const char *usage_const = "Usage: gtags [-ciIOqvw][-d tag-file][-f file][-n 
number][dbpath]\n";
+const char *usage_const = "Usage: gtags [-ciIOqvw][-d tag-file][-f file][-n 
number][-l arg][dbpath]\n";
 const char *help_const = "Options:\n\
 -c, --compact\n\
        Make GTAGS in compact format.\n\
@@ -29,6 +29,14 @@
 -i, --incremental\n\
        Update tag files incrementally. You had better use\n\
        global(1) with the -u option.\n\
+-l, --follow-links dirs|files|both|none\n\
+       Control how symbolic links are followed.\n\
+       By default, gtags will follow all symbolic links.  Depending on\n\
+       how your source tree is arranged, this may not be desirable.\n\
+       The argument dirs will cause gtags to only follow symbolic\n\
+       links that point to directories, files will only follow\n\
+       links to files, both will follow all links, and none\n\
+       will ignore all symbolic links.\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 -ur --exclude='*.o' global-5.7.7/gtags/gtags.1 
global-5.7.7-hacking/gtags/gtags.1
--- global-5.7.7/gtags/gtags.1  2009-12-19 02:49:28.000000000 -0800
+++ global-5.7.7-hacking/gtags/gtags.1  2010-01-18 13:44:45.000000000 -0800
@@ -3,7 +3,7 @@
 .SH NAME
 gtags \- create tag files for global.
 .SH SYNOPSIS
-\fBgtags\fP [-ciIOqvw][-d \fItag-file\fP][-f \fIfile\fP][-n 
\fInumber\fP][\fIdbpath\fP]
+\fBgtags\fP [-ciIOqvw][-d \fItag-file\fP][-f \fIfile\fP][-n \fInumber\fP][-l 
\fIarg\fP][\fIdbpath\fP]
 .br
 .SH DESCRIPTION
 \fBGtags\fP recursively collect the source files under
@@ -62,6 +62,15 @@
 Update tag files incrementally. You had better use
 \fBglobal\fP(1) with the -u option.
 .TP
+\fB-l\fP, \fB--follow-links\fP \fIdirs|files|both|none\fP
+Control how symbolic links are followed.
+By default, gtags will follow all symbolic links.  Depending on
+how your source tree is arranged, this may not be desirable.
+The argument \fIdirs\fP will cause gtags to only follow symbolic
+links that point to directories, \fIfiles\fP will only follow
+links to files, \fIboth\fP will follow all links, and \fInone\fP
+will ignore all symbolic links.
+.TP
 \fB-n\fP, \fB--max-args\fP \fInumber\fP
 Maximum number of arguments for \fBgtags-parser\fP(1).
 By default, gtags invokes \fBgtags-parser\fP with arguments
diff -ur --exclude='*.o' global-5.7.7/gtags/gtags.c 
global-5.7.7-hacking/gtags/gtags.c
--- global-5.7.7/gtags/gtags.c  2009-12-19 02:49:27.000000000 -0800
+++ global-5.7.7-hacking/gtags/gtags.c  2010-01-18 13:54:25.000000000 -0800
@@ -88,6 +88,7 @@
  */
 int do_path;
 int convert_type = PATH_RELATIVE;
+int followflags = FOLLOWF_BOTH;
 
 int extractmethod;
 int total;
@@ -126,6 +127,7 @@
        {"quiet", no_argument, NULL, 'q'},
        {"verbose", no_argument, NULL, 'v'},
        {"warning", no_argument, NULL, 'w'},
+       {"follow-links", required_argument, NULL, 'l'},
 
        /*
         * The following are long name only.
@@ -163,7 +165,7 @@
        int option_index = 0;
        STATISTICS_TIME *tim;
 
-       while ((optchar = getopt_long(argc, argv, "cd:f:iIn:oOqvwse", 
long_options, &option_index)) != EOF) {
+       while ((optchar = getopt_long(argc, argv, "cd:f:iIl:n:oOqvwse", 
long_options, &option_index)) != EOF) {
                switch (optchar) {
                case 0:
                        /* already flags set */
@@ -209,6 +211,18 @@
                case 'I':
                        Iflag++;
                        break;
+               case 'l':
+                       if (!strncmp (optarg, "files", 5))
+                               followflags = FOLLOWF_FILE;
+                       else if (!strncmp (optarg, "dirs", 4))
+                               followflags = FOLLOWF_DIR;
+                       else if (!strncmp (optarg, "both", 4))
+                               followflags = FOLLOWF_BOTH;
+                       else if (!strncmp (optarg, "none", 4))
+                               followflags = FOLLOWF_NONE;
+                       else
+                               die ("Unknown --follow-links argument: %s", 
optarg);
+                       break;
                case 'n':
                        max_args = atoi(optarg);
                        if (max_args <= 0)
@@ -585,7 +599,7 @@
                if (file_list)
                        find_open_filelist(file_list, root);
                else
-                       find_open(NULL);
+                       find_open(NULL, followflags);
                while ((path = find_read()) != NULL) {
                        const char *fid;
                        int n_fid = 0;
@@ -888,7 +902,7 @@
        if (file_list)
                find_open_filelist(file_list, root);
        else
-               find_open(NULL);
+               find_open(NULL, followflags);
        /*
         * Add tags.
         */
diff -ur --exclude='*.o' global-5.7.7/gtags/manual.in 
global-5.7.7-hacking/gtags/manual.in
--- global-5.7.7/gtags/manual.in        2009-12-19 02:49:27.000000000 -0800
+++ global-5.7.7-hacking/gtags/manual.in        2010-01-18 13:18:56.000000000 
-0800
@@ -25,7 +25,7 @@
 @HEADER        GTAGS,1,September 2009,GNU Project
 @NAME  gtags - create tag files for global.
 @SYNOPSIS
-       @name{gtags} [-ciIOqvw][-d @arg{tag-file}][-f @arg{file}][-n 
@address@hidden
+       @name{gtags} [-ciIOqvw][-d @arg{tag-file}][-f @arg{file}][-n 
@arg{number}][-l @address@hidden
 @DESCRIPTION
        @name{Gtags} recursively collect the source files under
        the current directory,
@@ -75,6 +75,14 @@
        @address@hidden, @option{--incremental}}
                Update tag files incrementally. You had better use
                @xref{global,1} with the -u option.
+       @address@hidden, @option{--follow-links} @arg{dirs|files|both|none}}
+               Control how symbolic links are followed.
+               By default, gtags will follow all symbolic links.  Depending on
+               how your source tree is arranged, this may not be desirable.
+               The argument @arg{dirs} will cause gtags to only follow symbolic
+               links that point to directories, @arg{files} will only follow
+               links to files, @arg{both} will follow all links, and @arg{none}
+               will ignore all symbolic links.
        @address@hidden, @option{--max-args} @arg{number}}
                Maximum number of arguments for @xref{gtags-parser,1}.
                By default, gtags invokes @name{gtags-parser} with arguments
diff -ur --exclude='*.o' global-5.7.7/libutil/find.c 
global-5.7.7-hacking/libutil/find.c
--- global-5.7.7/libutil/find.c 2009-12-19 02:49:27.000000000 -0800
+++ global-5.7.7-hacking/libutil/find.c 2010-01-18 13:54:52.000000000 -0800
@@ -91,6 +91,7 @@
 static regex_t *suff = &suff_area;     /* regex for suffixes */
 static STRBUF *list;
 static int list_count;
+static int follow_flags;
 static char **listarray;               /* list for skipping full path */
 static FILE *ip;
 static FILE *temp;
@@ -385,8 +386,9 @@
  *     r)              -1: error, 0: normal
  *
  * format of directory list:
- * |ddir1\0ffile1\0llink\0|
- * means directory 'dir1', file 'file1' and symbolic link 'link'.
+ * |ddir1\0ffile1\0Dlinkeddir\0Flinkedfile\0llink\0|
+ * means directory 'dir1', file 'file1', symbolic link to 'linkeddir',
+ * symbolic link to 'linkedfile', and symbolic link 'link'.
  */
 static int
 getdirs(const char *dir, STRBUF *sb)
@@ -394,6 +396,7 @@
        DIR *dirp;
        struct dirent *dp;
        struct stat st;
+       char islink;
 
        if ((dirp = opendir(dir)) == NULL)
                return -1;
@@ -402,14 +405,24 @@
                        continue;
                if (!strcmp(dp->d_name, ".."))
                        continue;
-               if (stat(makepath(dir, dp->d_name, NULL), &st) < 0) {
-                       warning("cannot stat '%s'. (Ignored)", dp->d_name);
+               if (lstat(makepath(dir, dp->d_name, NULL), &st) < 0) {
+                       warning("cannot lstat '%s'. (Ignored)", dp->d_name);
                        continue;
                }
+
+               if (S_ISLNK(st.st_mode)) {
+                       if (stat(makepath(dir, dp->d_name, NULL), &st) < 0) {
+                               warning("cannot stat '%s'. (Ignored)", 
dp->d_name);
+                               continue;
+                       }
+                       islink = 1;
+               } else
+                       islink = 0;
+
                if (S_ISDIR(st.st_mode))
-                       strbuf_putc(sb, 'd');
+                       strbuf_putc(sb, islink ? 'D' : 'd');
                else if (S_ISREG(st.st_mode))
-                       strbuf_putc(sb, 'f');
+                       strbuf_putc(sb, islink ? 'F' : 'f');
                else
                        strbuf_putc(sb, ' ');
                strbuf_puts(sb, dp->d_name);
@@ -425,14 +438,18 @@
  *                     If NULL, assumed '.' directory.
  */
 void
-find_open(const char *start)
+find_open(const char *start, int cl_follow_flags)
 {
        struct stack_entry *curp;
+
        assert(find_mode == 0);
        find_mode = FIND_OPEN;
 
        if (!start)
                start = "./";
+
+       follow_flags = cl_follow_flags;
+
        /*
         * setup stack.
         */
@@ -544,6 +561,17 @@
                         */
                                /* makepath() returns unsafe module local area. 
*/
                        strlimcpy(path, makepath(dir, unit, NULL), 
sizeof(path));
+                       if (type == 'D') {
+                               /*  Softlink to dir.  */
+                               if (!(follow_flags & FOLLOWF_DIR))
+                                       continue;
+                               type = 'd';
+                       } else if (type == 'F') {
+                               /*  Softlink to file.  */
+                               if (!(follow_flags & FOLLOWF_FILE))
+                                       continue;
+                               type = 'f';
+                       }
                        if (type == 'd')
                                strcat(path, "/");
                        if (skipthisfile(path))
@@ -554,6 +582,7 @@
                                 * o directory
                                 * o file which does not exist
                                 * o dead symbolic link
+                                * XXX ewhac: Is this test necessary?  Is 
stat(2) known to lie?
                                 */
                                if (!test("f", path)) {
                                        if (test("d", path))
diff -ur --exclude='*.o' global-5.7.7/libutil/find.h 
global-5.7.7-hacking/libutil/find.h
--- global-5.7.7/libutil/find.h 2009-12-19 02:49:27.000000000 -0800
+++ global-5.7.7-hacking/libutil/find.h 2010-01-18 13:16:19.000000000 -0800
@@ -21,9 +21,15 @@
 #ifndef _FIND_H_
 #define _FIND_H_
 
-void find_open(const char *);
+void find_open(const char *, int follow_flags);
 void find_open_filelist(const char *, const char *);
 char *find_read(void);
 void find_close(void);
 
+/*  follow_flags  */
+#define FOLLOWF_NONE    0
+#define FOLLOWF_FILE    1
+#define FOLLOWF_DIR     2
+#define FOLLOWF_BOTH    (FOLLOWF_FILE | FOLLOWF_DIR)
+
 #endif /* ! _FIND_H_ */
-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may 
contain
confidential information.  Any unauthorized review, use, disclosure or 
distribution
is prohibited.  If you are not the intended recipient, please contact the 
sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------




reply via email to

[Prev in Thread] Current Thread [Next in Thread]