#!/usr/bin/env ruby # Duplicated from Braid::Command.run. :( def die(msg) puts "Braid: Error: #{msg}" exit(1) end # If we assume Ruby >= 2.0, we can use __dir__. libdir = File.expand_path(File.dirname(File.realpath(__FILE__)) + '/../lib') unless File.exists?(libdir) # Don't silently fall back to a different globally installed copy of Braid! die "Cannot find Braid's 'lib' directory." end $LOAD_PATH.unshift(libdir) require 'braid' require 'rubygems' require 'main' Home = File.expand_path(ENV['HOME'] || '~') # mostly blantantly stolen from ara's punch script # main kicks ass! Main { description <<-TXT braid is a simple tool to help track git repositories inside a git repository. Run 'braid commandname help' for more details. All operations will be executed in the braid/track branch. You can then merge back or cherry-pick changes. TXT # The "main" library doesn't provide a way to do this?? def check_no_extra_args! if @argv.length > 0 die 'Extra argument(s) passed to command.' end end mode(:add) { description <<-TXT Add a new mirror to be tracked. * adds metadata about the mirror to .braids.json * adds the git remotes to .git/config * fetches and merges remote code into given directory Name defaults: * remote/path # => path * remote/path/trunk # => path * remote/path.git # => path TXT examples <<-TXT . braid add http://remote/path.git local/dir . braid add http://remote/path local/dir TXT mixin :argument_url, :optional_local_path, :option_branch, :option_tag, :option_revision, :option_verbose, :option_path run { check_no_extra_args! Braid.verbose = verbose Braid::Command.run(:add, url, {'path' => local_path, 'branch' => branch, 'tag' => tag, 'revision' => revision, 'remote_path' => path}) } } mode(:update) { description <<-TXT Update a braid mirror. * get new changes from remote * always creates a merge commit * updates metadata in .braids.json when revisions are changed * removes the git remote by default, --keep can be used to suppress that Defaults to updating all unlocked mirrors if none is specified. TXT examples <<-TXT . braid update . braid update local/dir TXT mixin :optional_local_path, :option_head, :option_revision, :option_tag, :option_branch, :option_verbose, :option_keep_remote run { check_no_extra_args! options = { 'branch' => branch, 'tag' => tag, 'revision' => revision, 'head' => head, 'keep' => keep } Braid.verbose = verbose Braid::Command.run(:update, local_path, options) } } mode(:remove) { description <<-TXT Remove a mirror. * removes metadata from .braids.json * removes the local directory and commits the removal * removes the git remote by default, --keep can be used to suppress that TXT examples <<-TXT . braid remove local/dir TXT mixin :argument_local_path, :option_verbose, :option_keep_remote run { check_no_extra_args! options = { :keep => keep } Braid.verbose = verbose Braid::Command.run(:remove, local_path, options) } } mode(:diff) { description <<-TXT Show diff of local changes to mirror. Additional arguments for "git diff" may be passed. "--" should be used to ensure they are not parsed as Braid options. File paths to limit the diff are relative to the downstream repository (for more convenient completion), even though file paths in the diff are relative to the mirror. TXT mixin :optional_local_path, :option_verbose, :option_keep_remote synopsis (Main::Usage.default_synopsis(self) + ' [-- git_diff_arg*]') run { if @argv.length > 0 && @argv[0] == '--' @argv.shift end options = { 'keep' => keep, 'git_diff_args' => @argv } Braid.verbose = verbose Braid::Command.run(:diff, local_path, options) } } mode(:push) { description <<-TXT Push local mirror changes to remote. TXT mixin :argument_local_path, :option_branch, :option_verbose, :option_keep_remote run { check_no_extra_args! options = { 'keep' => keep, 'branch' => branch } Braid.verbose = verbose Braid::Command.run(:push, local_path, options) } } mode(:setup) { description <<-TXT Set up git remotes. TXT mixin :optional_local_path, :option_verbose, :option_force run { check_no_extra_args! Braid.verbose = verbose Braid.force = force Braid::Command.run(:setup, local_path) } } mode(:version) { description 'Show braid version.' run { check_no_extra_args! puts "braid #{Braid::VERSION}" } } mode(:status) { description 'Show the status of all tracked mirrors (and if updates are available).' mixin :optional_local_path, :option_verbose run { check_no_extra_args! Braid.verbose = verbose Braid::Command.run(:status, local_path) } } mixin(:argument_local_path) { argument(:local_path) { attr } } mixin(:optional_local_path) { argument(:local_path) { optional attr } } mixin(:argument_url) { argument(:url) { attr } } mixin(:option_branch) { option(:branch, :b) { optional argument :required desc 'remote branch name to track' attr } } mixin(:option_tag) { option(:tag, :t) { optional argument :required desc 'remote tag name to track' attr } } mixin(:option_path) { option(:path, :p) { optional argument :required desc 'remote path' attr } } mixin(:option_revision) { option(:revision, :r) { optional argument :required desc 'revision to track' attr } } mixin(:option_head) { option(:head) { optional desc 'unused option' attr } } mixin(:option_verbose) { option(:verbose, :v) { optional desc 'log shell commands' attr } } mixin(:option_force) { option(:force, :f) { optional desc 'force' attr } } mixin(:option_keep_remote) { option(:keep) { optional desc 'do not remove the remote' attr } } run { help! } }