Could I do this blind relative to absolute path conversion (for perforce depot paths) better?

Posted by wonderfulthunk on Stack Overflow See other posts from Stack Overflow or by wonderfulthunk
Published on 2010-05-14T18:59:00Z Indexed on 2010/05/14 19:04 UTC
Read the original article Hit count: 223

I need to "blindly" (i.e. without access to the filesystem, in this case the source control server) convert some relative paths to absolute paths. So I'm playing with dotdots and indices. For those that are curious I have a log file produced by someone else's tool that sometimes outputs relative paths, and for performance reasons I don't want to access the source control server where the paths are located to check if they're valid and more easily convert them to their absolute path equivalents.

I've gone through a number of (probably foolish) iterations trying to get it to work - mostly a few variations of iterating over the array of folders and trying delete_at(index) and delete_at(index-1) but my index kept incrementing while I was deleting elements of the array out from under myself, which didn't work for cases with multiple dotdots. Any tips on improving it in general or specifically the lack of non-consecutive dotdot support would be welcome.

Currently this is working with my limited examples, but I think it could be improved. It can't handle non-consecutive '..' directories, and I am probably doing a lot of wasteful (and error-prone) things that I probably don't need to do because I'm a bit of a hack.

I've found a lot of examples of converting other types of relative paths using other languages, but none of them seemed to fit my situation.

These are my example paths that I need to convert, from:

//depot/foo/../bar/single.c

//depot/foo/docs/../../other/double.c

//depot/foo/usr/bin/../../../else/more/triple.c

to:

//depot/bar/single.c

//depot/other/double.c

//depot/else/more/triple.c

And my script:

begin

paths = File.open(ARGV[0]).readlines

puts(paths)

new_paths = Array.new

paths.each { |path|
  folders = path.split('/')
  if ( folders.include?('..') )
    num_dotdots = 0
    first_dotdot = folders.index('..')
    last_dotdot = folders.rindex('..')
    folders.each { |item|
      if ( item == '..' )
        num_dotdots += 1
      end
    }
    if ( first_dotdot and ( num_dotdots > 0 ) ) # this might be redundant?
      folders.slice!(first_dotdot - num_dotdots..last_dotdot) # dependent on consecutive dotdots only
    end
  end

  folders.map! { |elem| 
    if ( elem !~ /\n/ )
      elem = elem + '/' 
    else
      elem = elem
    end
  }
  new_paths << folders.to_s

}

puts(new_paths)


end

© Stack Overflow or respective owner

Related posts about ruby

Related posts about relative-path