bug-stow
[Top][All Lists]
Advanced

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

Re: [Bug-stow] [Patch] Option to exclude files for stow/unstow.


From: Cedric Ware
Subject: Re: [Bug-stow] [Patch] Option to exclude files for stow/unstow.
Date: Sun, 14 Jul 2002 02:17:13 +0200
User-agent: Mutt/1.3.28i

> I also prefer the shell pattern.

All right...  Here is a preliminary patch.  It doesn't use glob
(usage is more complicated) but translates globbing patterns into
regular expressions.  Both syntaxes are accepted, see the manpage
for details.

Sparse testing seems to indicate that it works for stowing but
apparently not for unstowing, and I don't really understand why.
Is there another place than Unstow for erasing links?

                                        Thank you,
                                        Cedric Ware.

diff -urN stow-1.3.3.bak/stow.8 stow-1.3.3/stow.8
--- stow-1.3.3.bak/stow.8       Sat Jan  5 16:06:37 2002
+++ stow-1.3.3/stow.8   Sun Jul 14 02:06:40 2002
@@ -194,6 +194,33 @@
 Set the target directory to DIR instead of the parent of the stow
 directory.
 .TP
+.I "-e EXPR"
+.TP
+.I --exclude=EXPR
+Exclude files matching expression EXPR. Several such exclusions
+can be specified with as many `-e' directives. The expression is
+either a regular expression, surrounded by a pair of slashes, or
+a shell globbing pattern. Note that this does not affect files
+under directories that are directly symlinked into the target tree.
+Possible behaviors are:
+.IP
+-
+an expression not containing any slash (not including those
+surrounding a regexp) will match file and directory names;
+e.g. `b*1*' or `/^b.*1/' will match `binary1' but not `bin/1';
+.IP
+-
+an expression containing slashes will match path names, relative
+to any subdirectory; e.g. `b*/1' or `/b.*/1/' will match bin/1
+as well as `libexec/bin86/1';
+.IP
+-
+a shell globbing pattern beginning with `./' or a regexp anchored
+to `^' will match directories relative to the stow directory;
+e.g. `./b*/1' or `/^b.*/1(/|$)' will files named `1' in package
+directories beginning with `b', but not in the subdirectory `bin'
+of package `a'.
+.TP
 .I -v
 .TP
 .I --verbose[=N]
diff -urN stow-1.3.3.bak/stow.in stow-1.3.3/stow.in
--- stow-1.3.3.bak/stow.in      Sat Jan  5 12:27:01 2002
+++ stow-1.3.3/stow.in  Sun Jul 14 02:03:49 2002
@@ -39,6 +39,9 @@
 $Stow = undef;
 $Target = undef;
 $Restow = 0;
+$Exclude = undef;
+$Exclude_paths = undef;
address@hidden = ();
 
 
 # FIXME: use Getopt::Long
@@ -81,6 +84,14 @@
       $Restow = 1;
     } elsif ($opt =~ /^vers(i(on?)?)?$/i) {
       &version();
+    } elsif ($opt =~ /^e(x(c(l(u(de?)?)?)?)?)?/i) {
+      $remainder = $';
+      if ($remainder =~ /^=/) {
+       $remainder = $';
+      } else {
+       $remainder = shift;
+      }
+      push(@Exclude_list, $remainder);
     } else {
       &usage(($opt =~ /^h(e(lp?)?)?$/) ? undef :
             "unknown or ambiguous option: $opt");
@@ -105,6 +116,10 @@
        $Delete = 1;
       } elsif ($_ eq 'R') {
        $Restow = 1;
+      } elsif ($_ eq 'e') {
+       $_ = (join('', @opts) || shift);
+       @opts = ();
+       push(@Exclude_list, $_);
       } elsif ($_ eq 'V') {
        &version();
       } else {
@@ -139,6 +154,47 @@
   }
 }
 
+# Process excluded patterns
+if (@Exclude_list) {
+  $Exclude = "";
+  $Exclude_paths = "";
+  foreach $_ (@Exclude_list) {
+    if (m,^/.*/$,) {
+      # regexp
+      $_ = substr($_, 1, length() - 2) . '|';
+      if (m,/,) {
+       $Exclude_paths .= $_;
+      } else {
+       $Exclude .= $_;
+      }
+      next;
+    }
+    # Convert glob-pattern to regexp.
+    local($pathexpr) = m,/,;
+    s,/+,/,;                   # delete redundant slashes
+    s,^,_,;
+    s,\\([^*?[\]\\]),\1,;      # cut '\' before any char not special for glob
+    s,([.+|^\$(){}]),\\\1,;    # quote chars special for RE but not glob
+    s,([^\\])\*,\1\[^/]*,;     # unquoted '*' -> '[^/]*'
+    s,([^\\])\?,\1\[^/],;      # unquoted '?' -> '[^/]'
+    s,^_,,;
+    s,(^|/)\[\^/]\*,\1\[^./].*,;       # first char in name should not be '.'
+    s,(^|/)\[\^/],\1\[^./],;
+
+    if (/^\\\.\//) {
+      $Exclude_paths .= "^$'|";        # anchor path relative to ^ (i.e. $Stow)
+    } elsif ($pathexpr) {
+      s,^([^/]),(^|/)\1,;      # anchor path relative to directories
+      s,([^/])$,\1(\$|/),;
+      $Exclude_paths .= "$_|";
+    } else {
+      $Exclude .= "^$_\$|";    # anchor path with ^$ (within a directory)
+    }
+  }
+
+  chop($Exclude, $Exclude_paths);      # delete trailing '|'
+}
+
 if ($Delete || $Restow) {
   @Collections = @ARGV;
   &Unstow('', &RelativePath($Target, $Stow));
@@ -225,6 +281,10 @@
   closedir(DIR);
   foreach $content (@contents) {
     next if (($content eq '.') || ($content eq '..'));
+    if (($Exclude) && ($content =~ $Exclude)) {
+      warn ("OMIT " . &JoinPaths($dir, $content) . "\n") if ($Verbose);
+      next;
+    }
     $empty = 0;
     if (-l &JoinPaths($Target, $targetdir, $content)) {
       ($linktarget = readlink(&JoinPaths($Target,
@@ -237,6 +297,10 @@
       if ($stowmember = &FindStowMember(&JoinPaths($Target,
                                                   $targetdir),
                                        $linktarget)) {
+       if (($Exclude_paths) && ($stowmember =~ $Exclude_paths)) {
+         warn ("OMIT " . &JoinPaths($dir, $content) . "\n") if ($Verbose);
+         next;
+       }
        @stowmember = split(/\/+/, $stowmember);
        $collection = shift(@stowmember);
        if (grep(($collection eq $_), @Collections)) {
@@ -334,6 +398,12 @@
   closedir(DIR);
   foreach $content (@contents) {
     next if (($content eq '.') || ($content eq '..'));
+    if ((($Exclude) && ($content =~ $Exclude))
+       || (($Exclude_paths)
+           && (&JoinPaths($dir, $content) =~ $Exclude_paths))) {
+      warn ("OMIT " . &JoinPaths($dir, $content) . "\n") if ($Verbose);
+      next;
+    }
     if (-d &JoinPaths($Stow, $dir, $content)) {
       &StowDir(&JoinPaths($dir, $content), $stow);
     } else {



reply via email to

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