lib/dotter/cli.rb in dotter_dotfiles-0.2.0 vs lib/dotter/cli.rb in dotter_dotfiles-0.3.0
- old
+ new
@@ -3,188 +3,203 @@
require 'dotter/gitrepo'
require 'dotter/version'
require 'dotter/configuration'
require 'dotter/package'
require 'dotter/publicgitrepo'
+require 'dotter/foreigngitrepo'
require 'pathname'
+require 'git'
module Dotter
-class CLI < Thor
- include Utilities
- desc "version", "Print the dotter version"
- def version
- puts "This is dotter #{Dotter::VERSION}"
- end
- desc "init", "Initialise the directory structure for ~/dotfiles"
- def init
- puts "Initialising ~/dotfiles"
- puts "Creating the dotfiles directory."
- FileUtils.mkpath(dotfiles_path)
- go_to_dotfiles
- puts "Creating the directory for the combined public dotfiles."
- FileUtils.mkpath('public')
- puts "Creating an initial package for dotter."
- FileUtils.mkpath('dotter/.dotter/gitrepos')
- FileUtils.mkpath('dotter/.dotter/indexes/')
- # If we don't do this now, we'll get a nasty exception if we ever access the configuration.
- FIleUtils.touch('dotter/.dotter/Dotfile')
- end
- desc "list", "List all packages present in ~/dotfiles"
- def list
- puts "List of packages in ~/dotfiles"
- all_package_names.each do |package|
- puts package
- end
- end
- desc "stow PACKAGE", "Stow the given package name."
- def stow(package)
- package = Package.new(package)
- if package.stowed?
- error "Package #{package} is already stowed."
- exit(1)
- end
- puts "Stowing package #{package}"
- puts package.stow
- end
- desc "unstow PACKAGE", "Unstow the given package name."
- def unstow(package)
- package = Package.new(package)
- if package.unstowed?
- error "Package #{package} is not stowed."
- exit(1)
- end
- puts "Unstowing package #{package}"
- puts package.unstow
- end
- desc "track PACKAGE", "Begin tracking the given package with Git"
- def track(package)
- puts "Initialising Git repository for package #{package}"
- package = Package.new(package)
- package.track
- puts "Repository for package #{package} initialised. Git's metadata is stored in #{package.repo.metadata_path.to_s}"
- puts "Creating an initial snapshot to serve as a starting point."
- repo = package.repo
- repo.add('.')
- repo.commit_all("Initial snapshot of the package's contents")
- puts "Initial snapshot created."
- end
- desc "publish PACKAGE", "Make a package available in your public dotfiles repository"
- def publish(package)
- puts "Making package #{package} public"
- public_repo = PublicGitRepo.new
- puts public_repo.add_package(package)
- end
- desc "unpublish PACKAGE", "Make a package private after publishing it."
- def unpublish(package)
- puts "Making package #{package} private again"
- public_repo = PublicGitRepo.new
- public_repo.remove_package(package)
- end
- method_option :commit_message, :required => true, :aliases => "-m"
- method_option :all, :type => :boolean, :aliases => "-a"
- desc "commit PACKAGE", "Commit your changes to a Git-tracked package."
- def commit(package)
- package = Package.new(package)
- if package.untracked?
- error "Package #{package} is not tracked by Git."
- exit 1
- end
- puts "Committing the changes to package #{package} with commit message #{options.commit_message}."
- commit_message = options.commit_message
- repo = package.repo
- if options.all
- repo.commit_all(commit_message)
- else
- repo.commit(commit_message)
- end
- end
- desc "update PACKAGE", "Updates the specified package"
- def update(package)
- puts "Updating the contents / symlinks for package #{package}"
- package = Package.new(package)
- if package.unstowed?
- error "Package #{package} is not stowed and therefore cannot be updated."
- exit 1
- end
- package.update
- end
- desc "update_all", "Updates all stowed packages."
- def update_all()
- puts "Updating all stowed packages"
- all_packages = []
- all_package_names.each do |package|
- all_packages.push(Package.new(package.to_s))
- end
- stowed_packages = all_packages.select { |package| package.stowed? }
- stowed_packages.each do |package|
- puts "Updating #{package}"
- package.update
- end
- end
- desc "import PATH PACKAGE", "Imports a file or directory into the specified package"
- def import(path, package)
- puts "Importing #{path} into package #{package}"
- filepath = Pathname.new(File.expand_path(path))
- packagepath = package_path(package)
- if not Dir.exist?(packagepath.to_s) then FileUtils.mkpath(packagepath.to_s) end
- homepath = Pathname.new(File.expand_path('~'))
- relative_filepath = filepath.relative_path_from(homepath)
- complete_path = packagepath + relative_filepath
- FileUtils.copy(File.expand_path(path), complete_path.to_s)
- puts "File imported successfully. Update the package to make the symlink."
- end
- desc "import_repo REPO_URL PACKAGE", "Clones the specified git repository as the contents of the specified Package."
- def import_repo(repo_url, package)
- puts "Cloning repository #{repo_url} into package #{package}"
- end
- desc "clone REPO_URL", "Clones the dotfiles / packages of the specified repository into ~/dotfiles. Will overwrite any existing data."
- def clone(repo_url)
- puts "Cloning repository #{repo_url} directly into ~/dotfiles"
- end
- desc "status PACKAGE", "Obtain the repository status of a Git-tracked package."
- def status(package)
- package = Package.new(package)
- if package.untracked?
- error "Package #{package} is not tracked by Git."
- exit 1
- end
- metadata_path = repo_path(package.to_s)
- metadata_indexes_path = index_path(package.to_s)
- # Punt because it does this better than ruby-git.
- system({"GIT_DIR" => metadata_path.to_s, "GIT_INDEX_FILE" => metadata_indexes_path.to_s}, "git status")
- end
- desc "add PACKAGE FILE", "Add a file from a package to the next commit of that package."
- def add(package,file)
- package = Package.new(package)
- if package.untracked?
- error "Package #{package} is not tracked by Git."
- exit 1
- end
- puts "Marking #{file} to be committed for package #{package}"
- repo = package.repo
- repo.add(file)
+ class CLI < Thor
+ include Utilities
+ desc 'version', 'Print the dotter version'
+ def version
+ puts "This is dotter #{Dotter::VERSION}"
end
- desc "reset PACKAGE", "Reset what will be commmitted in the next commit to the given package."
- def reset(package)
- package = Package.new(package)
- if package.untracked?
- error "Package #{package} is not tracked by Git."
- exit 1
- end
- puts "Resetting what will be committed to package #{package}"
- repo = package.repo
- repo.reset()
- end
- desc "log PACKAGE", "View the commit log of a package."
- def log(package)
- package = Package.new(package)
- if package.untracked?
- error "Package #{package} is not tracked by Git."
- exit 1
- end
- puts "Obtaining the log of package #{package}"
- repo = package.repo
- repo.log.each do |commit|
- puts "[#{commit.date}] #{commit.message} (#{commit.author.name})"
- end
- end
-end
+ desc 'init', 'Initialise the directory structure for ~/dotfiles'
+ def init
+ puts 'Initialising ~/dotfiles'
+ puts 'Creating the dotfiles directory.'
+ FileUtils.mkpath(dotfiles_path)
+ go_to_dotfiles
+ puts 'Creating the directory for the combined public dotfiles.'
+ FileUtils.mkpath('public')
+ puts 'Creating an initial package for dotter.'
+ FileUtils.mkpath('dotter/.dotter/gitrepos')
+ FileUtils.mkpath('dotter/.dotter/indexes/')
+ # If we don't do this now, we'll get a nasty exception if we ever access the configuration.
+ FileUtils.touch('dotter/.dotter/Dotfile')
+ end
+ desc 'list', 'List all packages present in ~/dotfiles'
+ def list
+ puts 'List of packages in ~/dotfiles'
+ all_package_names.each do |package|
+ puts package
+ end
+ end
+ desc 'stow PACKAGE', 'Stow the given package name.'
+ def stow(package)
+ package = Package.new(package)
+ if package.stowed?
+ error "Package #{package} is already stowed."
+ exit(1)
+ end
+ puts "Stowing package #{package}"
+ puts package.stow
+ end
+ desc 'unstow PACKAGE', 'Unstow the given package name.'
+ def unstow(package)
+ package = Package.new(package)
+ if package.unstowed?
+ error "Package #{package} is not stowed."
+ exit(1)
+ end
+ puts "Unstowing package #{package}"
+ puts package.unstow
+ end
+ desc 'track PACKAGE', 'Begin tracking the given package with Git'
+ def track(package)
+ puts "Initialising Git repository for package #{package}"
+ package = Package.new(package)
+ package.track
+ puts "Repository for package #{package} initialised. Git's metadata is stored in #{package.repo.metadata_path}"
+ puts 'Creating an initial snapshot to serve as a starting point.'
+ repo = package.repo
+ repo.add('.')
+ repo.commit_all("Initial snapshot of the package's contents")
+ puts 'Initial snapshot created.'
+ end
+ desc 'publish PACKAGE', 'Make a package available in your public dotfiles repository'
+ def publish(package)
+ puts "Making package #{package} public"
+ public_repo = PublicGitRepo.new
+ puts public_repo.add_package(package)
+ end
+ desc 'unpublish PACKAGE', 'Make a package private after publishing it.'
+ def unpublish(package)
+ puts "Making package #{package} private again"
+ public_repo = PublicGitRepo.new
+ public_repo.remove_package(package)
+ end
+ method_option :commit_message, required: true, aliases: '-m'
+ method_option :all, type: :boolean, aliases: '-a'
+ desc 'commit PACKAGE', 'Commit your changes to a Git-tracked package.'
+ def commit(package)
+ package = Package.new(package)
+ if package.untracked?
+ error "Package #{package} is not tracked by Git."
+ exit 1
+ end
+ puts "Committing the changes to package #{package} with commit message #{options.commit_message}."
+ commit_message = options.commit_message
+ repo = package.repo
+ if options.all
+ repo.commit_all(commit_message)
+ else
+ repo.commit(commit_message)
+ end
+ end
+ desc 'update PACKAGE', 'Updates the specified package. For packages imported from external repositories, also updates the repository.'
+ def update(package)
+ puts "Updating the contents / symlinks for package #{package}"
+ package = Package.new(package)
+ if package.unstowed?
+ error "Package #{package} is not stowed and therefore cannot be updated."
+ exit 1
+ end
+ package.update
+ end
+ desc 'update_all', 'Updates all stowed packages.'
+ def update_all
+ puts 'Updating all stowed packages'
+ all_packages = []
+ all_package_names.each do |package|
+ all_packages.push(Package.new(package.to_s))
+ end
+ stowed_packages = all_packages.select(&:stowed?)
+ stowed_packages.each do |package|
+ puts "Updating #{package}"
+ package.update
+ end
+ end
+ desc 'import PATH PACKAGE', 'Imports a file or directory into the specified package'
+ def import(path, package)
+ puts "Importing #{path} into package #{package}"
+ filepath = Pathname.new(File.expand_path(path))
+ packagepath = package_path(package)
+ FileUtils.mkpath(packagepath.to_s) unless Dir.exist?(packagepath.to_s)
+ homepath = Pathname.new(File.expand_path('~'))
+ relative_filepath = filepath.relative_path_from(homepath)
+ complete_path = packagepath + relative_filepath
+ FileUtils.copy(File.expand_path(path), complete_path.to_s)
+ puts 'File imported successfully. Update the package to make the symlink.'
+ end
+ desc 'import_repo REPO_URL PACKAGE', 'Clones the specified git repository as the contents of the specified Package.'
+ def import_repo(repo_url, package)
+ puts "Cloning repository #{repo_url} into package #{package}"
+ ForeignGitRepo.new(package, true, repo_url)
+ puts "Repository #{repo_url} successfully cloned into #{package}."
+ # We need to manually set the package as tracked to avoid calling init() again.
+ config = Configuration.new
+ config.track(package)
+ config.set_type(package, 'git_repo')
+ config.set_url(package, repo_url)
+ end
+ desc 'clone REPO_URL', 'Clones the dotfiles / packages of the specified repository into ~/dotfiles. Will overwrite any existing data.'
+ def clone(repo_url)
+ puts "Cloning repository #{repo_url} directly into ~/dotfiles"
+ repo = Git.clone(repo_url, @@dotfiles_path.to_s)
+ puts "Due to implementation difficulties, all the the commit history and state information will be lost."
+ go_to_dotfiles
+ `rm -rf .git`
+ `rm -rf dotter/*`
+ `touch dotter/Dotfile`
+ end
+ desc 'status PACKAGE', 'Obtain the repository status of a Git-tracked package.'
+ def status(package)
+ package = Package.new(package)
+ if package.untracked?
+ error "Package #{package} is not tracked by Git."
+ exit 1
+ end
+ metadata_path = repo_path(package.to_s)
+ metadata_indexes_path = index_path(package.to_s)
+ # Punt because it does this better than ruby-git.
+ system({ 'GIT_DIR' => metadata_path.to_s, 'GIT_INDEX_FILE' => metadata_indexes_path.to_s }, 'git status')
+ end
+ desc 'add PACKAGE FILE', 'Add a file from a package to the next commit of that package.'
+ def add(package, file)
+ package = Package.new(package)
+ if package.untracked?
+ error "Package #{package} is not tracked by Git."
+ exit 1
+ end
+ puts "Marking #{file} to be committed for package #{package}"
+ repo = package.repo
+ repo.add(file)
+ end
+ desc 'reset PACKAGE', 'Reset what will be commmitted in the next commit to the given package.'
+ def reset(package)
+ package = Package.new(package)
+ if package.untracked?
+ error "Package #{package} is not tracked by Git."
+ exit 1
+ end
+ puts "Resetting what will be committed to package #{package}"
+ repo = package.repo
+ repo.reset
+ end
+ desc 'log PACKAGE', 'View the commit log of a package.'
+ def log(package)
+ package = Package.new(package)
+ if package.untracked?
+ error "Package #{package} is not tracked by Git."
+ exit 1
+ end
+ puts "Obtaining the log of package #{package}"
+ repo = package.repo
+ repo.log.each do |commit|
+ puts "[#{commit.date}] #{commit.message} (#{commit.author.name})"
+ end
+ end
+ end
end