bug-global
[Top][All Lists]
Advanced

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

Re: Following Symbolic Links


From: Petr Uzel
Subject: Re: Following Symbolic Links
Date: Mon, 29 Jun 2009 10:15:06 +0200
User-agent: Mutt/1.5.19 (2009-01-05)

Hi,

On Fri, Jun 26, 2009 at 05:51:53PM -0700, Leo L. Schwab wrote:
>       A colleague had trouble running 'gtags' in a source tree with
> recursive symlinks.  Next thing I knew, I was bashing this out.
> 
>       This patch adds a new argument to gtags: --follow-links.  Note that
> I completely wrote this before I found last month's email thread on the
> subject, so my embodiment may not be precisely what everyone had in mind.
> 
>       I hacked this together in a few hours, and it has received minimal
> testing.  At the very least it should be good as a basis for discussion.
> All feedback welcome.

I did a simple test with a quilt usecase (as described in [1]) and
'gtags -l files' works OK. Many thanks for the patch!

[1] http://www.mail-archive.com/address@hidden/msg00523.html


> 
>                                       Thanks,
>                                       Schwab
> ----
> diff -ur --exclude='*.o' global-5.7.5/doc/gtags.ref 
> global-5.7.5-hacking/doc/gtags.ref
> --- global-5.7.5/doc/gtags.ref        2009-03-13 17:30:38.000000000 -0700
> +++ global-5.7.5-hacking/doc/gtags.ref        2009-06-26 15:56:43.000000000 
> -0700
> @@ -4,7 +4,7 @@
>  @unnumberedsubsec SYNOPSIS
>  @noindent
>  @quotation
> -gtags [-ciIOqvw][-f file][-n address@hidden
> +gtags [-ciIOqvw][-f file][-n number][-l address@hidden
>  @end quotation
>  @unnumberedsubsec DESCRIPTION
>  Gtags recursively collect the source files under
> @@ -52,6 +52,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.5/gtags/const.h 
> global-5.7.5-hacking/gtags/const.h
> --- global-5.7.5/gtags/const.h        2009-03-13 17:30:38.000000000 -0700
> +++ global-5.7.5-hacking/gtags/const.h        2009-06-26 15:56:43.000000000 
> -0700
> @@ -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][-f file][-n 
> number][dbpath]\n";
> +const char *usage_const = "Usage: gtags [-ciIOqvw][-f file][-n number][-l 
> arg][dbpath]\n";
>  const char *help_const = "Options:\n\
>  -c, --compact\n\
>         Make GTAGS in compact format.\n\
> @@ -26,6 +26,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.5/gtags/gtags.1 
> global-5.7.5-hacking/gtags/gtags.1
> --- global-5.7.5/gtags/gtags.1        2009-03-13 17:30:38.000000000 -0700
> +++ global-5.7.5-hacking/gtags/gtags.1        2009-06-26 15:56:43.000000000 
> -0700
> @@ -3,7 +3,7 @@
>  .SH NAME
>  gtags \- create tag files for global.
>  .SH SYNOPSIS
> -\fBgtags\fP [-ciIOqvw][-f \fIfile\fP][-n \fInumber\fP][\fIdbpath\fP]
> +\fBgtags\fP [-ciIOqvw][-f \fIfile\fP][-n \fInumber\fP][-l 
> \fIarg\fP][\fIdbpath\fP]
>  .br
>  .SH DESCRIPTION
>  \fBGtags\fP recursively collect the source files under
> @@ -58,6 +58,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.5/gtags/gtags.c 
> global-5.7.5-hacking/gtags/gtags.c
> --- global-5.7.5/gtags/gtags.c        2009-03-13 17:30:37.000000000 -0700
> +++ global-5.7.5-hacking/gtags/gtags.c        2009-06-26 16:09:59.000000000 
> -0700
> @@ -85,6 +85,7 @@
>   */
>  int do_path;
>  int convert_type = PATH_RELATIVE;
> +int followflags = FOLLOWF_BOTH;
>  
>  int extractmethod;
>  int total;
> @@ -122,6 +123,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.
> @@ -162,7 +164,7 @@
>       int optchar;
>       int option_index = 0;
>  
> -     while ((optchar = getopt_long(argc, argv, "cf:iIn:oOqvwse", 
> long_options, &option_index)) != EOF) {
> +     while ((optchar = getopt_long(argc, argv, "cf:iIl:n:oOqvwse", 
> long_options, &option_index)) != EOF) {
>               switch (optchar) {
>               case 0:
>                       /* already flags set */
> @@ -201,6 +203,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-flags argument: %s", 
> optarg);
> +                     break;
>               case 'n':
>                       max_args = atoi(optarg);
>                       if (max_args <= 0)
> @@ -502,7 +516,7 @@
>       if (file_list)
>               find_open_filelist(file_list, root);
>       else
> -             find_open(NULL);
> +             find_open(NULL, followflags);
>       total = 0;
>       while ((path = find_read()) != NULL) {
>               const char *fid;
> @@ -806,7 +820,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.5/gtags/manual.in 
> global-5.7.5-hacking/gtags/manual.in
> --- global-5.7.5/gtags/manual.in      2009-03-13 17:30:37.000000000 -0700
> +++ global-5.7.5-hacking/gtags/manual.in      2009-06-26 15:35:25.000000000 
> -0700
> @@ -25,7 +25,7 @@
>  @HEADER      GTAGS,1,January 2009,GNU Project
>  @NAME        gtags - create tag files for global.
>  @SYNOPSIS
> -     @name{gtags} [-ciIOqvw][-f @arg{file}][-n @address@hidden
> +     @name{gtags} [-ciIOqvw][-f @arg{file}][-n @arg{number}][-l 
> @address@hidden
>  @DESCRIPTION
>       @name{Gtags} recursively collect the source files under
>       the current directory,
> @@ -72,6 +72,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.5/libutil/find.c 
> global-5.7.5-hacking/libutil/find.c
> --- global-5.7.5/libutil/find.c       2009-03-13 17:30:37.000000000 -0700
> +++ global-5.7.5-hacking/libutil/find.c       2009-06-26 16:11:32.000000000 
> -0700
> @@ -78,6 +78,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;
> @@ -372,8 +373,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)
> @@ -381,6 +383,7 @@
>       DIR *dirp;
>       struct dirent *dp;
>       struct stat st;
> +     char islink;
>  
>       if ((dirp = opendir(dir)) == NULL)
>               return -1;
> @@ -389,14 +392,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);
> @@ -412,14 +425,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.
>        */
> @@ -531,6 +548,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))
> @@ -541,6 +569,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.5/libutil/find.h 
> global-5.7.5-hacking/libutil/find.h
> --- global-5.7.5/libutil/find.h       2009-03-13 17:30:37.000000000 -0700
> +++ global-5.7.5-hacking/libutil/find.h       2009-06-26 14:58:31.000000000 
> -0700
> @@ -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_ */
> 
> 
> _______________________________________________
> Bug-global mailing list
> address@hidden
> http://lists.gnu.org/mailman/listinfo/bug-global

-- 
Best regards / s pozdravem

Petr Uzel, Packages maintainer
---------------------------------------------------------------------
SUSE LINUX, s.r.o.                          e-mail: address@hidden
Lihovarská 1060/12                          http://www.suse.cz
190 00 Prague 9                             
Czech Republic                              




reply via email to

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