The attached two patches for contrib/hook-scripts/check-mime-type.pl
came via a GitHub PR [1] a few days ago...

They can be applied in sequence:
svn-patch-01-c73cb4415d.txt
svn-patch-02-68cc555740.txt

In principle I think the changes are useful, though might change
behavior in a surprising way for those who are using the hook as it
stands now.

Would it make sense to copy check-mime-type.pl, calling it, say,
check-mime-type-2.pl, and apply the changes to that file, keeping the
original as it is now?

[1] https://github.com/apache/subversion/pull/22

Cheers,
Nathan
From c73cb4415da492d574d6bdc2ff2d1b602981e91e Mon Sep 17 00:00:00 2001
From: maddes-b <madde...@users.noreply.github.com>
Date: Mon, 7 Sep 2020 20:06:56 +0200
Subject: [PATCH] Check also property-modified files in hook script
 check-mime-type.pl
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* contrib/hook-scripts/check-mime-type.pl:
  (proplist) add property-modified files for checks

Patch by: Matthias Bücher <maddes+subvers...@maddes.net>
Suggested by: Leo Davis [1]

[1] 
https://mail-archives.apache.org/mod_mbox/subversion-dev/201403.mbox/%3c1576503.m6xb7ud...@hurry.speechfxinc.com%3E
---
 contrib/hook-scripts/check-mime-type.pl | 41 ++++++++++++++-----------
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/contrib/hook-scripts/check-mime-type.pl 
b/contrib/hook-scripts/check-mime-type.pl
index 3ded119f27..79c37d26eb 100755
--- a/contrib/hook-scripts/check-mime-type.pl
+++ b/contrib/hook-scripts/check-mime-type.pl
@@ -1,18 +1,19 @@
 #!/usr/bin/env perl
 
 # ====================================================================
-# commit-mime-type-check.pl: check that every added file has the
-# svn:mime-type property set and every added file with a mime-type
-# matching text/* also has svn:eol-style set. If any file fails this
-# test the user is sent a verbose error message suggesting solutions and
-# the commit is aborted.
+# check-mime-type.pl: check that every added or property-modified file
+# has the svn:mime-type property set and every added or property-modified
+# file with a mime-type matching text/* also has svn:eol-style set.
+# If any file fails this test the user is sent a verbose error message
+# suggesting solutions and the commit is aborted.
 #
-# Usage: commit-mime-type-check.pl REPOS TXN-NAME
+# Usage: check-mime-type.pl REPOS TXN-NAME
 # ====================================================================
-# Most of commit-mime-type-check.pl was taken from
+# Most of check-mime-type.pl was taken from
 # commit-access-control.pl, Revision 9986, 2004-06-14 16:29:22 -0400.
 # ====================================================================
 # Copyright (c) 2000-2004 CollabNet.  All rights reserved.
+# Copyright (c) 2014-2020 Apache Software Foundation (ASF).
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution.  The terms
@@ -25,6 +26,9 @@
 # history and logs, available at http://subversion.tigris.org/.
 # ====================================================================
 
+use strict;
+use Carp;
+
 # Turn on warnings the best way depending on the Perl version.
 BEGIN {
   if ( $] >= 5.006_000)
@@ -33,9 +37,6 @@ BEGIN {
     { $^W = 1; }
 }
 
-use strict;
-use Carp;
-
 
 ######################################################################
 # Configuration section.
@@ -100,19 +101,20 @@ my $tmp_dir = '/tmp';
 chdir($tmp_dir)
   or die "$0: cannot chdir `$tmp_dir': $!\n";
 
-# Figure out what files have added using svnlook.
-my @files_added;
+# Figure out what files have been added/property-modified using svnlook.
+my @paths_to_check;
+my $props_changed_re = qr/^(?:A |[U_ ]U)  (.*[^\/])$/;
 foreach my $line (&read_from_process($svnlook, 'changed', $repos, '-t', $txn))
   {
-               # Add only files that were added to @files_added
-    if ($line =~ /^A.  (.*[^\/])$/)
+    # Add only files that were added/property-modified to @paths_to_check
+    if ($line =~ /$props_changed_re/)
       {
-        push(@files_added, $1);
+        push(@paths_to_check, $1);
       }
   }
 
 my @errors;
-foreach my $path ( @files_added )
+foreach my $path ( @paths_to_check )
        {
                my $mime_type;
                my $eol_style;
@@ -183,8 +185,8 @@ if (@errors)
          join("\n", @errors), "\n\n",
                                 <<EOS;
 
-    Every added file must have the svn:mime-type property set. In
-    addition text files must have the svn:eol-style property set.
+    Every added/property-modified file must have the svn:mime-type property
+    set. In addition text files must have the svn:eol-style property set.
 
     For binary files try running
     svn propset svn:mime-type application/octet-stream path/of/file
@@ -211,6 +213,7 @@ sub usage
   die "usage: $0 REPOS TXN-NAME\n";
 }
 
+# Start a child process safely without using a shell
 sub safe_read_from_pipe
 {
   unless (@_)
@@ -255,6 +258,8 @@ sub safe_read_from_pipe
     }
 }
 
+# Use safe_read_from_pipe to start a child process safely and exit the
+# script if the child failed for whatever reason.
 sub read_from_process
   {
   unless (@_)
-- 
2.24.3 (Apple Git-128)

From 68cc555740b3f3f8f82a59cca34b1af247cc3909 Mon Sep 17 00:00:00 2001
From: maddes-b <madde...@users.noreply.github.com>
Date: Mon, 7 Sep 2020 20:13:55 +0200
Subject: [PATCH] Enhanced platform support of hook script check-mime-type.pl
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* contrib/hook-scripts/check-mime-type.pl:
  (svnlook) Cross Platform: sane executable determination

Patch by: Matthias Bücher <maddes+subvers...@maddes.net>

[1] http://perldoc.perl.org/perlport.html#PLATFORMS
---
 contrib/hook-scripts/check-mime-type.pl | 129 ++++++++++++++++++++----
 1 file changed, 109 insertions(+), 20 deletions(-)

diff --git a/contrib/hook-scripts/check-mime-type.pl 
b/contrib/hook-scripts/check-mime-type.pl
index 79c37d26eb..716b1a0792 100755
--- a/contrib/hook-scripts/check-mime-type.pl
+++ b/contrib/hook-scripts/check-mime-type.pl
@@ -28,6 +28,15 @@
 
 use strict;
 use Carp;
+use Config;
+use Cwd;
+use Env;
+use File::Which  qw(which);
+use File::Temp  qw(tempdir tempfile);
+
+my $old_dir;
+my $os_windows = $^O eq 'MSWin32';
+my $os_dos = $^O eq 'dos';
 
 # Turn on warnings the best way depending on the Perl version.
 BEGIN {
@@ -35,6 +44,12 @@ BEGIN {
     { require warnings; import warnings; }
   else
     { $^W = 1; }
+
+  $old_dir = getcwd;
+}
+
+END {
+  chdir($old_dir);
 }
 
 
@@ -42,31 +57,58 @@ BEGIN {
 # Configuration section.
 
 # Svnlook path.
-my $svnlook = "/usr/bin/svnlook";
+my $svnlook;
 
 # Since the path to svnlook depends upon the local installation
 # preferences, check that the required program exists to insure that
 # the administrator has set up the script properly.
 {
-  my $ok = 1;
-  foreach my $program ($svnlook)
+  my $svnlook_exe = 'svnlook' . $Config{_exe};
+  my @svnlook_paths;
+
+  if ($os_windows || $os_dos)
+    {
+      # On Windows/DOS the environment is available
+      my $svn_bindir = $ENV{'SVN_BINDIR'};
+      if (defined $svn_bindir and length $svn_bindir)
+        {
+          $svnlook_paths[++$#svnlook_paths] = "$svn_bindir/$svnlook_exe";
+        }
+
+      $svnlook = which($svnlook_exe);
+      if (defined $svnlook and length $svnlook)
+        {
+          $svnlook_paths[++$#svnlook_paths] = $svnlook;
+        }
+      undef $svnlook;
+    }
+
+  # On Unix the environment is empty, define fallback with absolute path
+  $svnlook_paths[++$#svnlook_paths] = "/usr/bin/$svnlook_exe";
+
+  foreach my $program (@svnlook_paths)
     {
       if (-e $program)
         {
           unless (-x $program)
             {
-              warn "$0: required program `$program' is not executable, ",
-                   "edit $0.\n";
-              $ok = 0;
+              warn "$0: program `$program' is not executable.\n";
+              next;
             }
+          $svnlook = $program;
+          last;
         }
       else
         {
-          warn "$0: required program `$program' does not exist, edit $0.\n";
-          $ok = 0;
+          warn "$0: program `$program' does not exist.\n";
+          next;
         }
     }
-  exit 1 unless $ok;
+  unless (defined $svnlook and length $svnlook)
+    {
+      warn "$0: required program `$svnlook_exe' does not exist or is not 
executable, maybe have to edit $0.\n";
+      exit 1;
+    }
 }
 
 ######################################################################
@@ -95,9 +137,9 @@ sub ACCESS_READ_WRITE () { 'read-write' }
 ######################################################################
 # Harvest data using svnlook.
 
-# Change into /tmp so that svnlook diff can create its .svnlook
+# Change into temp dir so that svnlook diff can create its .svnlook
 # directory.
-my $tmp_dir = '/tmp';
+my $tmp_dir = tempdir( TMPDIR => 1, CLEANUP => 1 );
 chdir($tmp_dir)
   or die "$0: cannot chdir `$tmp_dir': $!\n";
 
@@ -220,19 +262,66 @@ sub safe_read_from_pipe
     {
       croak "$0: safe_read_from_pipe passed no arguments.\n";
     }
-  print "Running @_\n";
-  my $pid = open(SAFE_READ, '-|', @_);
-  unless (defined $pid)
+
+  my $openfork_available = !($os_windows || $os_dos);
+  if ($openfork_available)
     {
-      die "$0: cannot fork: $!\n";
+      print "Running @_\n";
+      my $pid = open(SAFE_READ, '-|', @_);
+      unless (defined $pid)
+        {
+          die "$0: cannot fork: $!\n";
+        }
+      unless ($pid)
+        {
+          open(STDERR, ">&STDOUT")
+            or die "$0: cannot dup STDOUT: $!\n";
+          exec(@_)
+            or die "$0: cannot exec `@_': $!\n";
+        }
     }
-  unless ($pid)
+  else
     {
-      open(STDERR, ">&STDOUT")
-        or die "$0: cannot dup STDOUT: $!\n";
-      exec(@_)
-        or die "$0: cannot exec `@_': $!\n";
+      # Redirect the comment into a temp file and use that to work around
+      # Windows' (non-)handling of multi-line commands.
+      my @commandline = ();
+      my $command;
+      my $comment;
+
+      while ($command = shift)
+        {
+          if ("-m" eq $command)
+            {
+              $comment = shift;
+              my ($handle, $tmpfile) = tempfile( DIR => $tmp_dir);
+              print $handle $comment;
+              close($handle);
+
+              push(@commandline, "--file");
+              push(@commandline, $tmpfile);
+            }
+          else
+            {
+              # Munge the command to protect it from the command line
+              $command =~ s/\"/\\\"/g;
+              if ($command =~ m"\s") { $command = "\"$command\""; }
+              if ($command eq "") { $command = "\"\""; }
+              if ($command =~ m"\n")
+                {
+                  warn "$0: carriage return detected in command - may not 
work\n";
+                }
+              push(@commandline, $command);
+            }
+        }
+
+      print "Running @commandline\n";
+      if ( $comment ) { print $comment; }
+
+      # Now do the pipe.
+      open(SAFE_READ, "@commandline |")
+        or die "$0: cannot pipe to command: $!\n";
     }
+
   my @output;
   while (<SAFE_READ>)
     {
-- 
2.24.3 (Apple Git-128)

Reply via email to