class GitXplorer

Public Class Methods

new() click to toggle source
# File lib/git_xplorer.rb, line 82
def initialize
    @cwd = Array.new
    @repo = %x(git rev-parse --show-toplevel).split("/")[-1].strip
    @tree = refresh_tree
end

Public Instance Methods

cd(path = nil) click to toggle source
# File lib/git_xplorer.rb, line 11
def cd(path = nil)
    path ||= ""

    # No path means go to top-level
    @cwd.clear if (path.empty?)

    target = @tree.get(absolute_path(path))
    if (target.nil?)
        raise GitXplorer::Error::NoFileOrDirectory.new(path)
    elsif (!target.is_a?(GitXplorer::GitObject::Directory))
        raise GitXplorer::Error::NotDirectory.new(path)
    end

    path.split("/"). each do |dir|
        case dir
        when "."
            # Do nothing
        when ".."
            @cwd.delete_at(-1)
        else
            @cwd.push(dir)
        end
    end

    # Return the target
    return target
end
exist?(path) click to toggle source
# File lib/git_xplorer.rb, line 39
def exist?(path)
    return @tree.exist?(absolute_path(path))
end
get_completions(input) click to toggle source
# File lib/git_xplorer.rb, line 43
def get_completions(input)
    return @tree.get_completions(absolute_path(input))
end
get_filenames(dir = "", pattern = ".") click to toggle source
# File lib/git_xplorer.rb, line 47
def get_filenames(dir = "", pattern = ".")
    dir ||= ""
    pattern ||= "."

    found = %x(
        git log --diff-filter=ACR --name-only --pretty=tformat: \
        -- #{dir}
    ).split("\n").map do |file|
        file.gsub(/^#{dir}/, "")
    end.select do |file|
        file.match(/#{pattern}/)
    end

    return found
end
git(args, refresh = true) click to toggle source
# File lib/git_xplorer.rb, line 63
def git(args, refresh = true)
    if (args.match(/.*;.*/))
        raise GitXplorer::Error::NoSemicolonsAllowed.new
    end

    if (args.match(/(\$|<)\(.+\)/))
        raise GitXplorer::Error::NoSubshellsAllowed.new
    end

    if (args.match(/\&\&|\|\|/))
        raise GitXplorer::Error::NoChainingAllowed.new
    end

    out = %x(git #{args})
    refresh = true if (refresh.nil?)
    @tree = refresh_tree if (refresh)
    return out
end
ls(path = nil) click to toggle source
# File lib/git_xplorer.rb, line 88
def ls(path = nil)
    path = absolute_path(path)

    # Get target directory if it exists
    target = @tree.get(path)
    if (target.nil?)
        raise GitXplorer::Error::NoFileOrDirectory.new(path)
    end

    return target.children
end
pwd() click to toggle source
# File lib/git_xplorer.rb, line 100
def pwd
    # Return repo name if at top-level
    return @repo if (@cwd.empty?)

    # Return repo name followed by CWD
    return "#{@repo}/#{@cwd.join("/")}#{"/" if (!@cwd.empty?)}"
end
pwd_short() click to toggle source
# File lib/git_xplorer.rb, line 108
def pwd_short
    # Return repo name if at top-level
    return @repo if (@cwd.empty?)

    # Return only the last 3 directories if more than 3 deep
    return @cwd[-3..-1].join("/") if (@cwd.length >= 3)

    # Return repo name followed by CWD
    return "#{@repo}/#{@cwd.join("/")}#{"/" if (!@cwd.empty?)}"
end
show(file) click to toggle source
# File lib/git_xplorer.rb, line 152
def show(file)
    # Check if file exists
    if (!exist?(file))
        raise GitXplorer::Error::NoFileOrDirectory.new(file)
    end

    file, _, rev = absolute_path(file).partition(":")

    # Get target and ensure it's a file
    target = @tree.get(file)
    if (!target.is_a?(GitXplorer::GitObject::File))
        raise GitXplorer::Error::NotFile.new(file)
    end

    # If revision was specified, ensure it exists
    if (!rev.empty? && !target.has_child?(rev))
        raise GitXplorer::Error::InvalidRevision.new(rev)
    end

    # Default to newest revision
    rev = target.newest.name if (rev.empty?)

    system("git --no-pager show #{rev}:#{file}")
end
vim(file, readonly = false) click to toggle source
# File lib/git_xplorer.rb, line 177
def vim(file, readonly = false)
    # Check if file exists
    if (!exist?(file))
        raise GitXplorer::Error::NoFileOrDirectory.new(file)
    end

    file, _, rev = absolute_path(file).partition(":")

    # Get target and ensure it's a file
    target = @tree.get(file)
    if (!target.is_a?(GitXplorer::GitObject::File))
        raise GitXplorer::Error::NotFile.new(file)
    end

    # If revision was specified, ensure it exists
    if (!rev.empty? && !target.has_child?(rev))
        raise GitXplorer::Error::InvalidRevision.new(rev)
    end

    # Default to newest revision
    rev = target.newest.name if (rev.empty?)

    op = nil
    op = "vi" if (ScoobyDoo.where_are_you("vi"))
    op = "vim" if (ScoobyDoo.where_are_you("vim"))

    readonly ||= false
    if (readonly && op.nil?)
        system("git show #{rev}:#{file}")
    else
        name = "/tmp/gitXplorer_"
        name += File.read("/dev/urandom", 4).unpack("H*").join
        File.open(name, "w") do |f|
            f.write(%x(git show #{rev}:#{file}))
        end
        system("#{op}#{" -R" if (readonly)} #{name}")
        FileUtils.rm_f(name)
    end
end

Private Instance Methods

absolute_path(path = nil) click to toggle source
# File lib/git_xplorer.rb, line 5
def absolute_path(path = nil)
    path ||= ""
    return "#{@cwd.join("/")}#{"/" if (!@cwd.empty?)}#{path}"
end
refresh_tree() click to toggle source
# File lib/git_xplorer.rb, line 119
def refresh_tree
    # Create tree root
    tree = GitXplorer::GitObject::Directory.new("/", nil)

    # Add files to tree
    get_filenames.sort do |a, b|
        a.downcase <=> b.downcase
    end.each do |path|
        tree.add(path)
    end

    # Return the tree
    return tree
end