class Conjoiner::CLI

Public Instance Methods

clone(url) click to toggle source
# File lib/conjoiner/cli.rb, line 91
def clone(url)
  home                = Pathname.new(Dir.home)
  joined_dir          = home.join('joined')

  # Create repository pathname from the URL.
  git_clone_url       = GitCloneUrl.parse(url)
  path_parts          = git_clone_url.path.sub(%r{^/}, '').sub(/\.git$/, '').split('/')
  repository_pathname =
    joined_dir
    .join(git_clone_url.host)
    .join(*path_parts)

  # Clone is repository if it is not already present.
  if repository_pathname.exist?
    puts "Already cloned at #{repository_pathname}"
  else
    puts "Clone #{url} to #{repository_pathname}"
    repository_pathname.mkpath
    Git.clone(url, repository_pathname)
  end
rescue URI::Error
  puts "Invalid URL <#{url}>"
end
init_aspect(aspect = nil, year = nil) click to toggle source
# File lib/conjoiner/cli.rb, line 21
def init_aspect(aspect = nil, year = nil)
  aspect ||= configuration.default_aspect
  year   ||= Time.now.year

  puts "init aspect #{aspect} #{year}"

  home       = Pathname.new(Dir.home)
  dated_root = home.join(
    'joined',
    'git.andrewcant.ca',
    'andrew',
    'aspects',
    aspect,
    'dated',
    year.to_s
  )

  configuration.dated_repository_names(aspect).each do |name|
    repo = "gitolite@git.andrewcant.ca:andrew/aspects/#{aspect}/dated/#{year}/#{name}"
    dir  = dated_root.join(name)

    git =
      if dir.exist?
        begin
          git_open = Git.open(dir)
          puts "Open #{name}"
          git_open
        rescue Git::GitExecuteError
          puts "Init #{name}"
          Git.init(dir.to_s).tap do |git_init|
            git_init.commit('Initial commit', allow_empty: true)
          end
        end
      else
        puts "Clone #{name}"
        puts "  #{repo}"
        puts "  #{dir}"

        dir.mkpath
        Git.clone(repo, dir)
      end

    # Add any existing files.
    begin
      git.add(all: true)
      git.commit_all('Commit existing files')
    rescue Git::GitExecuteError
      # Nothing to do, continue with the rest of the sync.
    end

    # Ensure that the remote exists.
    if git.remotes.empty?
      puts 'Add remote....'
      git.add_remote('origin', repo)
    end

    # TODO: should set upstream for regular commits

    # Try synchronize the new commits with the remote origin.
    begin
      puts 'Rync with the remote'
      git.pull('origin')
      git.push('origin')
    rescue Git::GitExecuteError
      # Nothing to do, continue with the rest of the sync.
    end
  end
end
ls() click to toggle source
# File lib/conjoiner/cli.rb, line 281
def ls
  home       = Pathname.new(Dir.home)
  joined_dir = home.join('joined')
  result     = []
  joined_dir.find do |pathname|
    next unless pathname.directory? && pathname.join('.git').directory?

    if options[:origin]
      origin_url = Git.open(pathname).remote('origin').url
      result.push(origin_url) if origin_url
    elsif options[:noorigin]
      origin_url = Git.open(pathname).remote('origin').url
      result.push(pathname) unless origin_url
    else
      result.push(pathname)
    end

    Find.prune
  end

  result.sort.each { |x| puts x }
end
show(aspect = nil, year = nil) click to toggle source
# File lib/conjoiner/cli.rb, line 242
def show(aspect = nil, year = nil)
  aspect ||= configuration.default_aspect
  year   ||= Time.now.year

  home = Pathname.new(Dir.home)
  joined_dir = home.join('joined')
  aspect_dir = joined_dir.join(
    'git.andrewcant.ca',
    'andrew',
    'aspects',
    aspect
  )

  gits =
    [
      aspect_dir.join('dated', year.to_s),
      aspect_dir.join('dated', (year - 1).to_s),
      aspect_dir.join('gtd'),
      aspect_dir.join('wiki'),
      aspect_dir.join('contacts'),
      aspect_dir.join('password-store')
    ].map { |x| x.glob('**/.git').map(&:dirname) }.flatten.map { |x| Git.open(x) }

  output =
    gits.map do |git|
      additions = git.status.added.count + git.status.changed.count
      OpenStruct.new( # rubocop:disable Style/OpenStructUse
        path:   Pathname.new(git.dir.to_s).relative_path_from(joined_dir).to_s,
        status: "+#{additions} -#{git.status.deleted.count} *#{git.status.untracked.count}"
      )
    end

  tp.set(:max_width, 256)
  tp(output, :path, :status)
end
sync(aspect = nil, year = nil) click to toggle source
# File lib/conjoiner/cli.rb, line 116
def sync(aspect = nil, year = nil)
  aspect ||= configuration.default_aspect
  year   ||= Time.now.year

  home = Pathname.new(Dir.home)
  joined_dir = home.join('joined')
  root = joined_dir.join(
    'git.andrewcant.ca',
    'andrew',
    'aspects',
    aspect
  )

  gits =
    [
      root.join('dated', year.to_s),
      root.join('dated', (year - 1).to_s),
      root.join('gtd'),
      root.join('wiki')
    ].map { |x| x.glob('**/.git').map(&:dirname) }.flatten.map { |x| Git.open(x) }

  gits.each do |git|
    print '<'
    # Add any existing files.
    begin
      git.add(all: true)
      git.commit_all('auto commit')
    rescue Git::GitExecuteError
      # Nothing to do, continue with the rest of the sync.
    end

    print '.'

    git.pull('origin')
    git.push('origin')

    print '>'
  end
  puts ''
end
syncer() click to toggle source
# File lib/conjoiner/cli.rb, line 158
def syncer
  year   ||= Time.now.year

  home = Pathname.new(Dir.home)
  joined_dir   = home.join('joined')
  aspects_root = joined_dir.join(
    'git.andrewcant.ca',
    'andrew',
    'aspects'
  )

  listen_pathnames =
    configuration.aspects.map do |aspect|
      aspect_dir = aspects_root.join(aspect)
      [
        aspect_dir.join('dated', year.to_s),
        aspect_dir.join('dated', (year - 1).to_s),
        aspect_dir.join('gtd'),
        aspect_dir.join('wiki')
      ]
    end
  # Flatten and include only existing directories.
  listen_pathnames =
    listen_pathnames.flatten.compact.select(&:directory?)

  # Find the repositories within those directories.
  listen_repository_pathnames =
    listen_pathnames.map { |x| x.glob('**/.git').map(&:dirname) }.flatten

  puts 'For these aspects:'
  configuration.aspects.each { |x| puts "  * #{x}" }
  puts 'Watch the following repositories:'
  listen_repository_pathnames.each { |x| puts "  * #{x}" }

  listener =
    Listen.to(
      *listen_repository_pathnames.map(&:to_s),
      ignore:         /#{File::SEPARATOR}\.git#{File::SEPARATOR}/o,
      latency:        5,
      wait_for_delay: 5
    ) do |modified, added, removed|
      changed_files = [modified, added, removed].flatten.compact.uniq
      changed_files
        .map { |file| listen_repository_pathnames.map(&:to_s).find { |repo| file.start_with?(repo) } }
        .compact
        .uniq
        .map { |x| Git.open(x) }
        .select { |x| x.status.added.any? || x.status.changed.any? || x.status.deleted.any? || x.status.untracked.any? } # rubocop:disable Layout/LineLength
        .each do |git|
          puts "Sync #{git.dir}"

          # Add any existing files.
          begin
            git.add(all: true)
            git.commit_all('auto commit')
          rescue Git::GitExecuteError
            # Nothing to do, continue with the rest of the sync.
          end

          # Sync the commits
          # TODO: needs conflict handling. Review what is done in gitdocs.
          begin
            git.pull('origin')
            git.push('origin')
          rescue => e # rubocop:disable Style/RescueStandardError
            puts "Error sycing #{git.dir}: #{e}"
          end
        end
    end

  listener.start
  puts 'Start listening...'
  begin
    sleep
  rescue Interrupt
    puts 'Exit'
    exit
  rescue SignalException => e
    puts "Exit on #{e}"
    exit
  end
end

Private Instance Methods

configuration() click to toggle source

@return [Conjoiner::Configuration]

# File lib/conjoiner/cli.rb, line 309
def configuration
  @configuration ||= Configuration.new
end