From 51f53632117097dad7c9c56d1f0ecc5f09338f54 Mon Sep 17 00:00:00 2001 From: Ole Tange Date: Fri, 25 Sep 2015 01:29:34 +0200 Subject: [PATCH] Fixed bug #45993: --wd ... should also work when run locally. --- doc/release_new_version | 5 ++ src/parallel | 52 +++++++++++-------- testsuite/tests-to-run/parallel-local-0.3s.sh | 12 +++++ testsuite/wanted-results/parallel-local-0.3s | 26 ++++++++++ 4 files changed, 74 insertions(+), 21 deletions(-) diff --git a/doc/release_new_version b/doc/release_new_version index dc82248c..5c7af9a0 100644 --- a/doc/release_new_version +++ b/doc/release_new_version @@ -232,6 +232,11 @@ New in this release: * <> GNU Parallel was used in: Large Scale Author Name Disambiguation in Digital Libraries http://ieeexplore.ieee.org/xpl/abstractReferences.jsp?tp=&arnumber=7004487&url=http%3A%2F%2Fieeexplore.ieee.org%2Fxpls%2Fabs_all.jsp%3Farnumber%3D7004487 * <> GNU Parallel was used (unfortunately with wrong citation) in: TADSim: Discrete Event-Based Performance Prediction for Temperature-Accelerated Dynamics http://vruehle.de/publications/2015c.pdf +http://www.researchgate.net/profile/Christoph_Junghans/publication/276178326_TADSim_Discrete_Event-Based_Performance_Prediction_for_Temperature-Accelerated_Dynamics/links/55562b6708ae980ca60c8369.pdf + +* GNU Parallel was cited in: Roary: rapid large-scale prokaryote pan genome analysis http://bioinformatics.oxfordjournals.org/content/early/2015/08/05/bioinformatics.btv421.full.pdf+html + +* GNU Parallel is used in TraitAR: https://testpypi.python.org/pypi/traitar/0.1.4 * Bug fixes and man page updates. diff --git a/src/parallel b/src/parallel index 7ddf9fdd..fb1e63ea 100755 --- a/src/parallel +++ b/src/parallel @@ -3503,6 +3503,23 @@ sub show_limits { sub __GENERIC_COMMON_FUNCTION__ {} +sub mkdir_or_die { + # If dir is not executable: die + my $dir = shift; + my @dir_parts = split(m:/:,$dir); + my ($ddir,$part); + while(defined ($part = shift @dir_parts)) { + $part eq "" and next; + $ddir .= "/".$part; + -d $ddir and next; + mkdir $ddir; + } + if(not -x $dir) { + ::error("Cannot write to $dir: $!"); + ::wait_and_exit(255); + } +} + sub tmpfile { # Create tempfile as $TMPDIR/parXXXXX # Returns: @@ -6710,6 +6727,16 @@ sub sshlogin_wrap { $ENV{'PARALLEL_SEQ'} = $self->seq(); $ENV{'PARALLEL_PID'} = $$; if($serverlogin eq ":") { + if($opt::workdir) { + # Create workdir if needed. Then cd to it. + my $wd = $self->workdir(); + if($opt::workdir eq "." or $opt::workdir eq "...") { + # If $wd does not start with '/': Prepend $HOME + $wd =~ s:^([^/]):$ENV{'HOME'}/$1:; + } + ::mkdir_or_die($wd); + $command = "cd ".::shell_quote_scalar($wd)." || exit 255; ".$command; + } if(@opt::env) { # Prepend with environment setter, which sets functions in zsh my ($csh_friendly,$envset,$bashfuncset) = env_as_eval(); @@ -6973,7 +7000,7 @@ sub workdir { $workdir = $opt::workdir; # Rsync treats /./ special. We dont want that $workdir =~ s:/\./:/:g; # Remove /./ - $workdir =~ s:/+$::; # Remove ending / if any + $workdir =~ s:(.)/+$:$1:; # Remove ending / if any $workdir =~ s:^\./::g; # Remove starting ./ if any } } else { @@ -9289,9 +9316,9 @@ sub new { $id =~ s/([^-_a-z0-9])/unpack("H*",$1)/ige; # Convert non-word chars to hex $id = "id-".$id; # To distinguish it from a process id my $parallel_dir = $ENV{'HOME'}."/.parallel"; - -d $parallel_dir or mkdir_or_die($parallel_dir); + -d $parallel_dir or ::mkdir_or_die($parallel_dir); my $parallel_locks = $parallel_dir."/semaphores"; - -d $parallel_locks or mkdir_or_die($parallel_locks); + -d $parallel_locks or ::mkdir_or_die($parallel_locks); my $lockdir = "$parallel_locks/$id"; my $lockfile = $lockdir.".lock"; if($count < 1) { ::die_bug("semaphore-count: $count"); } @@ -9400,7 +9427,7 @@ sub atomic_link_if_count_less_than { my $nlinks = $self->nlinks(); ::debug("sem","$nlinks<$self->{'count'} "); if($nlinks < $self->{'count'}) { - -d $self->{'lockdir'} or mkdir_or_die($self->{'lockdir'}); + -d $self->{'lockdir'} or ::mkdir_or_die($self->{'lockdir'}); if(not -e $self->{'idfile'}) { open (my $fh, ">", $self->{'idfile'}) or ::die_bug("write_idfile: $self->{'idfile'}"); @@ -9492,23 +9519,6 @@ sub unlock { ::debug("run", "unlocked\n"); } -sub mkdir_or_die { - # If dir is not writable: die - my $dir = shift; - my @dir_parts = split(m:/:,$dir); - my ($ddir,$part); - while(defined ($part = shift @dir_parts)) { - $part eq "" and next; - $ddir .= "/".$part; - -d $ddir and next; - mkdir $ddir; - } - if(not -w $dir) { - ::error("Cannot write to $dir: $!"); - ::wait_and_exit(255); - } -} - # Keep perl -w happy $opt::x = $Semaphore::timeout = $Semaphore::wait = diff --git a/testsuite/tests-to-run/parallel-local-0.3s.sh b/testsuite/tests-to-run/parallel-local-0.3s.sh index 0c67d64d..ca9f9c95 100644 --- a/testsuite/tests-to-run/parallel-local-0.3s.sh +++ b/testsuite/tests-to-run/parallel-local-0.3s.sh @@ -218,6 +218,18 @@ parallel --dryrun --joblog - echo ::: Only_this echo '**' +echo 'bug #45993: --wd ... should also work when run locally' +parallel --wd /bi 'pwd; echo $OLDPWD; echo' ::: fail +parallel --wd /bin 'pwd; echo $OLDPWD; echo' ::: OK +parallel --wd / 'pwd; echo $OLDPWD; echo' ::: OK +parallel --wd /tmp 'pwd; echo $OLDPWD; echo' ::: OK +parallel --wd ... 'pwd; echo $OLDPWD; echo' ::: OK | perl -pe 's/\d+/0/g' + +parallel --wd . 'pwd; echo $OLDPWD; echo' ::: OK + +echo '**' + + EOF echo '### 1 .par file from --files expected' find /tmp{/*,}/*.{par,tms,tmx} 2>/dev/null -mmin -10 | wc -l diff --git a/testsuite/wanted-results/parallel-local-0.3s b/testsuite/wanted-results/parallel-local-0.3s index 529569bb..2456fabb 100644 --- a/testsuite/wanted-results/parallel-local-0.3s +++ b/testsuite/wanted-results/parallel-local-0.3s @@ -451,5 +451,31 @@ parallel --dryrun --joblog - echo ::: Only_this echo Only_this echo '**' ** +echo 'bug #45993: --wd ... should also work when run locally' +bug #45993: --wd ... should also work when run locally +parallel --wd /bi 'pwd; echo $OLDPWD; echo' ::: fail +parallel: Error: Cannot write to /bi: No such file or directory +parallel --wd /bin 'pwd; echo $OLDPWD; echo' ::: OK +/bin +/home/tange/privat/parallel/testsuite +OK +parallel --wd / 'pwd; echo $OLDPWD; echo' ::: OK +/ +/home/tange/privat/parallel/testsuite +OK +parallel --wd /tmp 'pwd; echo $OLDPWD; echo' ::: OK +/tmp +/home/tange/privat/parallel/testsuite +OK +parallel --wd ... 'pwd; echo $OLDPWD; echo' ::: OK | perl -pe 's/\d+/0/g' +/home/tange/.parallel/tmp/aspire-0-0 +/home/tange/privat/parallel/testsuite +OK +parallel --wd . 'pwd; echo $OLDPWD; echo' ::: OK +/home/tange/privat/parallel/testsuite +/home/tange/privat/parallel/testsuite +OK +echo '**' +** ### 1 .par file from --files expected 1