⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svnshell.rb

📁 subversion-1.4.5.tar.gz 配置svn的源码
💻 RB
字号:
#!/usr/bin/env ruby## svnshell.rb : a Ruby-based shell interface for cruising 'round in#               the filesystem.## Usage: ruby svnshell.rb REPOS_PATH, where REPOS_PATH is a path to# a repository on your local filesystem.## NOTE: This program requires the Ruby readline extension.# See http://wiki.rubyonrails.com/rails/show/ReadlineLibrary# for details on how to install readline for Ruby.######################################################################### Copyright (c) 2000-2005 CollabNet.  All rights reserved.## This software is licensed as described in the file COPYING, which# you should have received as part of this distribution.  The terms# are also available at http://subversion.tigris.org/license-1.html.# If newer versions of this license are posted there, you may use a# newer version instead, at your option.########################################################################require "readline"require "shellwords"require "svn/fs"require "svn/core"require "svn/repos"# SvnShell: a Ruby-based shell interface for cruising 'round in#           the filesystem.class SvnShell  # A list of potential commands. This list is populated by   # the 'method_added' function (see below).  WORDS = []  # Check for methods that start with "do_"   # and list them as potential commands  class << self    def method_added(name)      if /^do_(.*)$/ =~ name.to_s        WORDS << $1      end    end  end    # Constructor for SvnShell  #  # path: The path to a Subversion repository  def initialize(path)    @repos_path = path    @path = "/"    self.rev = youngest_rev    @exited = false  end  # Run the shell  def run    # While the user hasn't typed 'exit' and there is still input to be read    while !@exited and buf = Readline.readline(prompt, true)      # Parse the command line into a single command and arguments      cmd, *args = Shellwords.shellwords(buf)      # Skip empty lines      next if /\A\s*\z/ =~ cmd.to_s      # Open a new connection to the repo      @fs = Svn::Repos.open(@repos_path).fs      setup_root      # Execute the specified command      dispatch(cmd, *args)      # Find a path that exists in the current revision      @path = find_available_path      # Close the connection to the repo      @root.close    end  end  # Private functions  private  # Get the current prompt string  def prompt    # Gather data for the prompt string    if rev_mode?      mode = "rev"      info = @rev    else      mode = "txn"      info = @txn    end    # Return the prompt string    "<#{mode}: #{info} #{@path}>$ "  end    # Dispatch a command to the appropriate do_* subroutine  def dispatch(cmd, *args)    # Dispatch cmd to the appropriate do_* function    if respond_to?("do_#{cmd}", true)      begin        __send__("do_#{cmd}", *args)      rescue ArgumentError        # puts $!.message        # puts $@        puts("Invalid argument for #{cmd}: #{args.join(' ')}")      end    else      puts("Unknown command: #{cmd}")      puts("Try one of these commands: ", WORDS.sort.join(" "))    end  end  # Output the contents of a file from the repository  def do_cat(path)    # Normalize the path to an absolute path    normalized_path = normalize_path(path)    # Check what type of node exists at the specified path    case @root.check_path(normalized_path)    when Svn::Core::NODE_NONE      puts "Path '#{normalized_path}' does not exist."    when Svn::Core::NODE_DIR      puts "Path '#{normalized_path}' is not a file."    else      # Output the file to standard out      @root.file_contents(normalized_path) do |stream|        puts stream.read(@root.file_length(normalized_path))      end    end  end  # Set the current directory  def do_cd(path="/")    # Normalize the path to an absolute path    normalized_path = normalize_path(path)    # If it's a valid directory, then set the directory    if @root.check_path(normalized_path) == Svn::Core::NODE_DIR      @path = normalized_path    else      puts "Path '#{normalized_path}' is not a valid filesystem directory."    end  end    # List the contents of the current directory or provided paths  def do_ls(*paths)    # Default to listing the contents of the current directory    paths << @path if paths.empty?        # Foreach path    paths.each do |path|      # Normalize the path to an absolute path      normalized_path = normalize_path(path)            # Is it a directory or file?      case @root.check_path(normalized_path)      when Svn::Core::NODE_DIR        # Output the contents of the directory        parent = normalized_path        entries = @root.dir_entries(parent)      when Svn::Core::NODE_FILE        # Split the path into directory and filename components        parts = path_to_parts(normalized_path)        name = parts.pop        parent = parts_to_path(parts)        # Output the filename        puts "#{parent}:#{name}"        # Double check that the file exists        # inside the parent directory        parent_entries = @root.dir_entries(parent)        if parent_entries[name].nil?          # Hmm. We found the file, but it doesn't exist inside          # the parent directory. That's a bit unusual.          puts "No directory entry found for '#{normalized_path}'"          next        else          # Save the path so it can be output in detail          entries = {name => parent_entries[name]}        end      else        # Path is not a directory or a file,        # so it must not exist        puts "Path '#{normalized_path}' not found."        next      end      # Output a detailed listing of the files we found      puts "   REV   AUTHOR  NODE-REV-ID     SIZE              DATE NAME"      puts "-" * 76      # For each entry we found...      entries.keys.sort.each do |entry|        # Calculate the full path to the directory entry        fullpath = parent + '/' + entry        if @root.dir?(fullpath)          # If it's a directory, output an extra slash          size = ''          name = entry + '/'        else          # If it's a file, output the size of the file          size = @root.file_length(fullpath).to_i.to_s          name = entry        end                # Output the entry        node_id = entries[entry].id.to_s        created_rev = @root.node_created_rev(fullpath)        author = @fs.prop(Svn::Core::PROP_REVISION_AUTHOR, created_rev).to_s        date = @fs.prop(Svn::Core::PROP_REVISION_DATE, created_rev)        args = [          created_rev, author[0,8],          node_id, size, date.strftime("%b %d %H:%M(%Z)"), name        ]        puts "%6s %8s <%10s> %8s %17s %s" % args              end    end  end  # List all currently open transactions available for browsing  def do_lstxns        # Get a sorted list of open transactions    txns = @fs.transactions    txns.sort    counter = 0        # Output the open transactions    txns.each do |txn|      counter = counter + 1      puts "%8s  " % txn            # Every six transactions, output an extra newline      if counter == 6        puts        counter = 0      end    end    puts  end    # Output the properties of a particular path  def do_pcat(path=nil)        # Default to the current directory    catpath = path ? normalize_path(path) : @path    # Make sure that the specified path exists    if @root.check_path(catpath) == Svn::Core::NODE_NONE      puts "Path '#{catpath}' does not exist."      return    end    # Get the list of properties    plist = @root.node_proplist(catpath)    return if plist.nil?    # Output each property     plist.each do |key, value|      puts "K #{key.size}"      puts key      puts "P #{value.size}"      puts value    end    # That's all folks!    puts 'PROPS-END'      end        # Set the current revision to view  def do_setrev(rev)        # Make sure the specified revision exists    begin      @fs.root(Integer(rev)).close    rescue Svn::Error      puts "Error setting the revision to '#{rev}': #{$!.message}"      return    end        # Set the revision    self.rev = Integer(rev)      end    # Open an existing transaction to view  def do_settxn(name)    # Make sure the specified transaction exists    begin      txn = @fs.open_txn(name)      txn.root.close    rescue Svn::Error      puts "Error setting the transaction to '#{name}': #{$!.message}"      return    end        # Set the transaction    self.txn = name      end  # List the youngest revision available for browsing  def do_youngest    rev = @fs.youngest_rev    puts rev  end    # Exit this program  def do_exit    @exited = true  end  # Find the youngest revision  def youngest_rev    Svn::Repos.open(@repos_path).fs.youngest_rev  end  # Set the current revision  def rev=(new_value)    @rev = new_value    @txn = nil    reset_root  end  # Set the current transaction  def txn=(new_value)    @txn = new_value    reset_root  end  # Check whether we are in 'revision-mode'  def rev_mode?    @txn.nil?  end    # Close the current root and setup a new one  def reset_root    if @root      @root.close      setup_root    end  end  # Setup a new root  def setup_root    if rev_mode?      @root = @fs.root(@rev)    else      @root = @fs.open_txn(name).root    end  end    # Convert a path into its component parts  def path_to_parts(path)    path.split(/\/+/)  end  # Join the component parts of a path into a string  def parts_to_path(parts)    normalized_parts = parts.reject{|part| part.empty?}    "/#{normalized_parts.join('/')}"  end    # Convert a path to a normalized, absolute path  def normalize_path(path)    # Convert the path to an absolute path    if path[0,1] != "/" and @path != "/"      path = "#{@path}/#{path}"    end    # Split the path into its component parts    parts = path_to_parts(path)        # Build a list of the normalized parts of the path     normalized_parts = []    parts.each do |part|      case part      when "."        # ignore      when ".."        normalized_parts.pop      else        normalized_parts << part      end    end    # Join the normalized parts together into a string    parts_to_path(normalized_parts)  end  # Find the parent directory of a specified path  def parent_dir(path)    normalize_path("#{path}/..")  end    # Try to land on the specified path as a directory.  # If the specified path does not exist, look for   # an ancestor path that does exist.  def find_available_path(path=@path)    if @root.check_path(path) == Svn::Core::NODE_DIR      path    else      find_available_path(parent_dir(path))    end  end  end# Autocomplete commandsReadline.completion_proc = Proc.new do |word|  SvnShell::WORDS.grep(/^#{Regexp.quote(word)}/)end# Output usage information if necessaryif ARGV.size != 1  puts "Usage: #{$0} REPOS_PATH"  exit(1)end# Create a new SvnShell with the command-line arguments and run itSvnShell.new(ARGV.shift).run

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -