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