ClearCase-SyncTree

 view release on metacpan or  search on metacpan

SyncTree.pm  view on Meta::CPAN

    if ($self->{branchoffroot}) {
	foreach my $e (@ele) {
	    my $sel = $ct->ls(['-d'], $e)->autochomp(1)->qx;
	    if ($sel =~ /^(.*?) +Rule:.*-mkbranch (.*?)\]?$/) {
		my ($ver, $bt) = ($1, $2);
		my $sil = $self->clone_ct({stdout=>0, stderr=>0});
		my $main = 'main';
		if ($sil->des(['-s'], "$e\@\@/main/0")->system) {
		    $main = ($ct->lsvtree($e)->autochomp(1)->qx)[0];
		    $main =~ s%^[^@]*\@\@[\\/](.*)\r?$%$1%;
		}
		my $re = $self->pbrtype($bt) ?
		  qr([\\/]${main}[\\/]$bt[\\/]\d+$) : qr([\\/]$bt[\\/]\d+$);
		if ($ver =~ m%$re%) {
		    $rc |= $ct->co($self->comment, $e)->system;
		} else {
		    my $r = $ct->mkbranch([@{$self->comment}, '-ver',
					      "/${main}/0", $bt], $e)->system;
		    if ($r) {
			$rc = 1;
		    } else {
			if ($ver !~ m%\@\@[\\/]${main}[\\/]0$%) {
			    $rc |= $dir ?
				$ct->merge(['-to', $e],
					   $ver)->stdout(0)->system :
				$ct->merge(['-ndata', '-to', $e],
					   $ver)->stdout(0)->system;
			    unlink("$e.contrib");
			}
		    }
		}
	    } else {
		$rc |= $ct->co($self->comment, $e)->system;
	    }
	}
    } else {
	$rc = $ct->co($self->comment, @ele)->system;
    }
    return $rc;
}

sub rmdirlinks {
    my $self = shift;
    return unless $self->{ST_DIRLNK};
    my $lsco = ClearCase::Argv->lsco([qw(-s -d -cview)]);
    for (sort {$b cmp $a} keys %{$self->{ST_DIRLNK}}) {
	my $dad = dirname $_;
	$self->branchco(1, $dad) unless $lsco->args($dad)->qx;
	$self->clone_ct->rm($_)->system;
	delete $self->{ST_SUB}->{exfiles}->{$_}; #If it is there
    }
}

sub mkrellink {
    my ($self, $src) = @_;
    my $txt = src_rlink($src);
    my $sbase = $self->srcbase;
    return $txt unless $self->{ST_RELLINKS} and ($txt =~ /^$sbase/);
    $txt =~ s%^$sbase/(.*)%$1%;
    $src =~ s%^$sbase/(.*)%$1%;
    my @t = split m%/%, $txt;
    my @s = split m%/%, $src;
    my $i = 0;
    while ($t[$i] eq $s[$i]) {
	$i++;
	shift @t;
	shift @s;
    }
    while ($i++ < $#s) { unshift @t, '..'; }
    $txt = join '/', @t;
    return $txt;
}

# Remove spurious names from restored directory
sub skimdir {
    my ($self, $dst, $pfx) = @_;
    my $flt = qr{^(\Q$pfx\E.*?)(?:/.*)?$}; # paths normalized
    opendir(DIR, $dst);
    my @f = grep !m%^\.\.?$%, readdir DIR;
    closedir DIR;
    my %ok = map {$_ => 1} grep s%$flt%$1%, keys %{$self->{ST_SRCMAP}};
    for (@f) {
	my $f = $pfx . $_;
	$self->{ST_SUB}->{exfiles}->{join('/', $dst, $_)}++ unless $ok{$f};
    }
}

sub vtree {
    my ($self, $dir) = @_;
    if (!exists $self->{ST_VT}->{$dir}) {
	my $vt = ClearCase::Argv->lsvtree({autochomp=>1}, [qw(-a -s -nco)]);
	# optimization: branch/0 of a directory is either empty or duplicate
	my @vt = reverse grep { m%[/\\](\d+)$% && $1>=1 } $vt->args($dir)->qx;
	$self->{ST_VT}->{$dir} = \@vt;
    }
    return $self->{ST_VT}->{$dir};
}

# Once a directory version was found, move it first in the list for next tries
sub raise_dver {
    my ($self, $i, $dir) = @_;
    return unless $i;
    my $vt = $self->{ST_VT}->{$dir};
    my $ver = splice @{$vt}, $i, 1;
    unshift @{$vt}, $ver;
}

# Reuse from removed elements, or create as view private, directories
sub reusemkdir {
    my ($self, $dref, $rref) = @_;
    my (%found, %dfound, %priv);
    my $snapview = $self->snapdest;
    my $ds = ClearCase::Argv->desc({stderr=>1},[qw(-s)]);
    my $dm = ClearCase::Argv->desc([qw(-fmt %m)]);
    my $rm = ClearCase::Argv->rm;
    my $lsco = ClearCase::Argv->lsco([qw(-s -d -cview)]);
    my $ln = ClearCase::Argv->ln;
    for my $dst (sort keys %{$dref}) {
	next if $dfound{$dst};
	my $reused;
	my($name, $dir) = fileparse($dst);
	if (!$priv{$dir}) {
	  if ($rref->{$dst}) {
	    $self->branchco(1, $dir) unless $lsco->args($dir)->qx;
	    $rm->args($dst)->system;
	  }
	  my $i = -1; #index in the vtree list
	VER: for (@{$self->vtree($dir)}) {
	    $i++;
	    my $dirext = "$_/$name";
	    # case-insensitive file test operator on Windows is a problem
	    if ($snapview ? $ds->args($dirext)->qx !~ /Error:/ : ecs($dirext)) {
	      next if $dm->args($dirext)->qx eq 'file element';
	      while (ccsymlink($dirext)) {
		$name = readcclink $dirext;
		$name =~ s/\@\@$//;
		$dirext = "$_/$name";
		# consider only relative, and local symlinks
		next VER if !ecs($dirext) ||
		  $dm->args($dirext)->qx eq 'file element';
	      }
	      $reused = 1;
	      $self->raise_dver($i, $dir);
	      $self->branchco(1, $dir) unless $lsco->args($dir)->qx;
	      $ln->args($dirext, $dst)->system;
	      # Need to reevaluate all the files under this dir
	      # The case of implicit dirs, is recorded as '.'
	      my $d = $dref->{$dst} eq '.'? '' : $dref->{$dst} . '/';
	      $self->skimdir($dst, $d) if $self->remove;
	      my $cmp = $self->no_cmp ? undef : $self->cmp_func;
	      my @keys = sort $d? grep m%^\Q$d\E%, keys %{$self->{ST_ADD}}
		: keys %{$self->{ST_ADD}};
	      for my $e (@keys) {
		my $edst = join '/', $self->dstbase, $e;
		my @intdir = split m%/%, $e;
		pop @intdir;
		if (@intdir) {
		  my $dd = $self->dstbase;
		  my $pf = '';
		  while (my $id = shift @intdir) {
		    $dd = join '/', $dd, $id;
		    $pf = $pf . $id . '/';
		    $self->skimdir($dd, $pf) if -d $dd && !$dfound{$dd}++;
		  }
		}
		# Problem: does it match the type under srcbase?
		if (-d $edst and !ccsymlink($edst)) { # We know it is empty
		  opendir(DIR, $edst);
		  my @f = grep !m%^\.\.?$%, readdir DIR;
		  closedir DIR;
		  if (@f) {
		    $self->branchco(1, $edst)
		      unless $lsco->args($edst)->qx;
		    $rm->args(map{join '/', $edst, $_} @f)->system;
		  }
		  $dfound{$edst}++; #Skip in this loop
		  next;
		}
		if (exists($self->{ST_ADD}->{$e}->{dst})) {
		  my $src = $self->{ST_ADD}->{$e}->{src};
		  my $dst = $self->{ST_ADD}->{$e}->{dst};
		  if (-e $dst) {
		    $self->{ST_MOD}->{$e} = $self->{ST_ADD}->{$e}
		      if $self->_needs_update($src, $dst, $cmp);
		    $found{$e}++; #Remove from the add list
		  }
		}
	      }
	      last;
	    }
	  }
	}
	if (!$reused) {
	    my $err;
	    mkpath($dst, {error => \$err, verbose => 0, mode => 0777});
	    $self->failm(join(': ', %{$err->[0]})) if $err and @{$err};
	    $priv{"${dst}/"}++;
	}
    }
    return %found;
}

# recursively record parent directories, and clashing objects to remove
sub recadd {
    my ($self, $src, $dst, $dir, $rm, $seen) = @_;
    my $dad = dirname($dst);
    return if $seen->{$dad}++ || (-d $dad && !ccsymlink($dad)); #exists, normal
    my $sdad = dirname($src);
    $self->recadd($sdad, $dad, $dir, $rm, $seen);
    $rm->{$dad}++ if -f $dad || ccsymlink($dad); #something clashing: remove
    $dir->{$dad} = $sdad;
}

sub add {
    my $self = shift;



( run in 1.051 second using v1.01-cache-2.11-cpan-483215c6ad5 )