class GithubExport::Command

Constants

ACCESS_TOKEN_NAME
ASSETS_LIST_FILENAME
ASSET_PATTERN
CHECK_MSG_NG
CHECK_MSG_OK

Public Instance Methods

all(repo) click to toggle source
# File lib/github_export/command.rb, line 19
def all(repo)
  repository(repo)
  milestones(repo)
  releases(repo)
  labels(repo)
  issues(repo)
  comments(repo)
  events(repo)
  issue_events(repo)
  assets
end
assets() click to toggle source
# File lib/github_export/command.rb, line 80
def assets
  files = Dir.glob(File.join(options[:output_dir], '**/*.json'))
  assets_list(*files)
  assets_download
  assets_check
end
assets_check() click to toggle source
# File lib/github_export/command.rb, line 130
def assets_check
  read_from_output_file(ASSETS_LIST_FILENAME).lines.map(&:strip).each do |line|
    path = File.join(options[:output_dir], URI.parse(line).path)
    fmt = File.exist?(path) ? CHECK_MSG_OK : CHECK_MSG_NG
    puts fmt % path
  end
end
assets_download() click to toggle source
# File lib/github_export/command.rb, line 99
def assets_download
  num = [options[:client_num].to_i, 1].max
  lines = read_from_output_file(ASSETS_LIST_FILENAME).lines.map(&:strip)
  tasks = lines.group_by.with_index{|_, i| i % num}
  tasks.each do |idx, task_lines|
    fork do
      task_lines.each do |url|
        uri = URI.parse(url)
        dest = File.join(options[:output_dir], uri.path)
        if options[:force] || !File.exist?(dest)
          verbose "DL #{url}"
          FileUtils.mkdir_p(File.dirname(dest))
          # Assets might be downloaded from S3 so we use curl (or httpclient?) without auth info instead of `client` object
          # File.binwrite(dest, client.get(url))
          cmd = "curl -f -o #{dest} #{url}"
          unless system(cmd)
            puts "Download Error #{cmd}"
          end
        else
          verbose "SKIP #{url}"
        end
      end
    end
    Process.waitall
  end
end
assets_list(*files) click to toggle source
# File lib/github_export/command.rb, line 89
def assets_list(*files)
  urls = files.map{|file|
    File.read(file).lines.map{|line| line.scan(ASSET_PATTERN)}.delete_if(&:empty?).flatten.uniq
  }.flatten.sort.uniq
  output_to_file(ASSETS_LIST_FILENAME, urls.join("\n"))
end
call_repo_method(repo, name, filename, api_opts = {}) click to toggle source
# File lib/github_export/command.rb, line 184
def call_repo_method(repo, name, filename, api_opts = {})
  results = client.send(name, repo, api_opts)
  output_to_file(filename, JSON.pretty_generate(results.map(&:to_attrs)))
end
client() click to toggle source
# File lib/github_export/command.rb, line 139
def client
  unless @client
    Octokit.auto_paginate = true
    access_token = options[:access_token]
    access_token ||= generate_access_token
    @client = Octokit::Client.new access_token: access_token
  end
  @client
end
comments(repo) click to toggle source
# File lib/github_export/command.rb, line 58
def comments(repo)
  call_repo_method(repo, :issues_comments, 'comments.json', sort: 'created', direction: 'asc')
end
events(repo) click to toggle source
# File lib/github_export/command.rb, line 63
def events(repo)
  call_repo_method(repo, :repository_events, 'events.json', sort: 'created', direction: 'asc')
end
generate_access_token() click to toggle source
# File lib/github_export/command.rb, line 151
def generate_access_token
  login = ask 'login: '
  pw = ask 'password: ', echo: false
  $stdout.print "\n" # For noecho
  client = Octokit::Client.new login: login, password: pw
  verbose(client.inspect)

  opts = {:scopes => ["repo", "user"], :note => ACCESS_TOKEN_NAME}
  two_fa_code = ask 'two-factor authentication OTP code(Optional): '
  unless two_fa_code.empty?
    opts[:headers] = { "X-GitHub-OTP" => two_fa_code }
  end
  verbose("client.create_authorization(#{opts.inspect})")
  begin
    res = client.create_authorization(opts)
    verbose("token: #{res.inspect}")
    return res[:token]
  rescue Octokit::Unauthorized => e
    puts_error "Authentication failed. Your login name or password is wrong."
    exit(1)
  rescue Octokit::OneTimePasswordRequired => e
    puts_error "You must specify two-factor authentication OTP code."
    exit(1)
  rescue Octokit::UnprocessableEntity => e
    if e.errors.any?{|err| err[:code] == 'already_exists' && err[:resource] == 'OauthAccess'}
      puts_error "Access Token named \"#{ACCESS_TOKEN_NAME}\" is already created." \
                 "\nPlease remove the personal access token named \"#{ACCESS_TOKEN_NAME}\" at https://github.com/settings/tokens ." \
                 "\nOr you can regenerate token on Edit view of the personal access token and add --access-token option to github_export command."
    end
    exit(1)
  end
end
issue_events(repo) click to toggle source
# File lib/github_export/command.rb, line 73
def issue_events(repo)
  call_repo_method(repo, :repository_issue_events, 'issue_events.json', sort: 'created', direction: 'asc')
end
issues(repo) click to toggle source
# File lib/github_export/command.rb, line 53
def issues(repo)
  call_repo_method(repo, :list_issues, 'issues.json', state: 'all', sort: 'created', direction: 'asc')
end
labels(repo) click to toggle source
# File lib/github_export/command.rb, line 48
def labels(repo)
  call_repo_method(repo, :labels, 'labels.json')
end
milestones(repo) click to toggle source
# File lib/github_export/command.rb, line 38
def milestones(repo)
  call_repo_method(repo, :list_milestones, 'milestones.json')
end
output_to_file(filename, content) click to toggle source
# File lib/github_export/command.rb, line 189
def output_to_file(filename, content)
  path = File.join(options[:output_dir], filename)
  FileUtils.mkdir_p(File.dirname(path))
  open(path, 'w') do |f|
    f.puts(content)
  end
end
puts_error(msg) click to toggle source
# File lib/github_export/command.rb, line 201
def puts_error(msg)
  $stderr.puts "\e[31m#{msg}\e[0m"
end
puts_info(msg) click to toggle source
# File lib/github_export/command.rb, line 205
def puts_info(msg)
  $stderr.puts "\e[0m#{msg}\e[0m"
end
read_from_output_file(filename) click to toggle source
# File lib/github_export/command.rb, line 197
def read_from_output_file(filename)
  File.read(File.join(options[:output_dir], filename))
end
releases(repo) click to toggle source
# File lib/github_export/command.rb, line 43
def releases(repo)
  call_repo_method(repo, :releases, 'releases.json')
end
repository(repo) click to toggle source
# File lib/github_export/command.rb, line 32
def repository(repo)
  result = client.repository(repo)
  output_to_file('repository.json', JSON.pretty_generate(result.to_attrs))
end
verbose(msg) click to toggle source
# File lib/github_export/command.rb, line 209
def verbose(msg)
  $stderr.puts "\e[34m#{msg}\e[0m" if options[:verbose]
end