sub add_new_path {
my ($self,$path) = @_;
my $canonical_path = get_canonical_path($path);
my @subpaths = splitdir($canonical_path);
for my $index (0..$#subpaths) {
next if (@subpaths[$index] eq ""); # Ignore empty strings
my $parent_path = abs_path(catdir(@subpaths[0..($index-1)]));
my $current_path = catdir($parent_path,@subpaths[$index]);
my $original_path_flag = ($index eq $#subpaths);
next if ($self->{"graph"}->has_vertex($current_path));
if (-l $current_path) {
my @resloved_links = resolve_symlink($current_path);
my $target_path = $resloved_links[1];
$self->add_path($target_path);
$self->{"graph"}->add_edge($parent_path,$current_path);
$self->{"graph"}->add_edge($current_path,$target_path);
$self->{"graph"}->set_vertex_attributes($current_path, { "type" => "link", "original" => $original_path_flag });
} elsif (-f $current_path) {
$self->{"graph"}->add_edge($parent_path,$current_path);
$self->{"graph"}->set_vertex_attributes($current_path, { "type" => "file", "original" => $original_path_flag });
} elsif (-d $current_path) {
$self->{"graph"}->add_edge($parent_path,$current_path);
$self->{"graph"}->set_vertex_attributes($current_path, { "type" => "dir", "original" => $original_path_flag });
}
}
}
sub resolve_symlink {
my ($file) = @_;
unless (file_name_is_absolute($file)) {
log_debug("Failed to resolve link $file");
return;
}
my @files;
my $origwd = getcwd;
my $rv = eval {
my $f = $file;
while (1) {
my $dir;
($f,$dir) = fileparse($f);
last unless (-d $dir);
chdir $dir or die "chdir $dir: $!";
push @files, catfile(getcwd,$f);
last unless (-l $f);
defined( $f = readlink $f ) or die "readlink $f (cwd=".getcwd."): $!";
}
1 }; my $err = $@ || 'unknown error';
chdir $origwd or (log_error("Failed to chdir $origwd: $!") && return);
die $err unless ($rv);
return @files ? @files : ($file);
}
####
/ (dir) -> /a (dir)
/a (dir) -> /a/b (dir)
/a/b/ (dir) -> /a/b/c (dir)
/a/b/c (dir) -> /a/b/c/file (file)
/ (dir) -> /p (link)
/p (dir) -> /a/b/c (dir)
##
##
/a/b/c/file1
/a/b/d/e/file2
##
##
/p/file1
/a/b/d/e/file2