1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: AGPL-3.0
5 class Repository < ArvadosBase
9 def attributes_for_display
10 super.reject { |x| x[0] == 'fetch_url' }
12 def editable_attributes
13 if current_user.is_admin
22 run_git 'show', commit_sha1
25 def cat_file commit_sha1, path
27 run_git 'cat-file', 'blob', commit_sha1 + ':' + path
30 def ls_tree_lr commit_sha1
32 run_git 'ls-tree', '-l', '-r', commit_sha1
35 # subtree returns a list of files under the given path at the
36 # specified commit. Results are returned as an array of file nodes,
37 # where each file node is an array [file mode, blob sha1, file size
38 # in bytes, path relative to the given directory]. If the path is
39 # not found, [] is returned.
40 def ls_subtree commit, path
43 ls_tree_lr(commit).each_line do |line|
44 mode, type, sha1, size, filepath = line.split
45 next if type != 'blob'
46 if filepath[0,path.length] == path and
47 (path == '' or filepath[path.length] == '/')
48 subtree << [mode.to_i(8), sha1, size.to_i,
49 filepath[path.length,filepath.length]]
55 # http_fetch_url returns the first http:// or https:// url (if any)
56 # in the api response's clone_urls attribute.
58 clone_urls.andand.select { |u| /^http/ =~ u }.first
63 # refresh fetches the latest repository content into the local
64 # cache. It is a no-op if it has already been run on this object:
65 # this (pretty much) avoids doing more than one remote git operation
66 # per Workbench request.
68 run_git 'fetch', http_fetch_url, '+*:*' unless @fresh
72 # run_git sets up the ARVADOS_API_TOKEN environment variable,
73 # creates a local git directory for this repository if necessary,
74 # executes "git --git-dir localgitdir {args to run_git}", and
75 # returns the output. It raises GitCommandError if git exits
79 workdir = File.expand_path uuid+'.git', Rails.configuration.repository_cache
80 if not File.exists? workdir
81 FileUtils.mkdir_p Rails.configuration.repository_cache
82 [['git', 'init', '--bare', workdir],
85 raise GitCommandError.new($?.to_s) unless $?.exitstatus == 0
90 [['git', '--git-dir', @workdir, 'config', '--local',
91 "credential.#{http_fetch_url}.username", 'none'],
92 ['git', '--git-dir', @workdir, 'config', '--local',
93 "credential.#{http_fetch_url}.helper",
94 '!cred(){ cat >/dev/null; if [ "$1" = get ]; then echo password=$ARVADOS_API_TOKEN; fi; };cred'],
95 ['git', '--git-dir', @workdir, 'config', '--local',
97 Rails.configuration.arvados_insecure_https ? 'false' : 'true'],
100 raise GitCommandError.new($?.to_s) unless $?.exitstatus == 0
104 merge('ARVADOS_API_TOKEN' => Thread.current[:arvados_api_token])
105 cmd = ['git', '--git-dir', @workdir] + gitcmd
106 io = IO.popen(env, cmd, err: [:child, :out])
109 # "If [io] is opened by IO.popen, close sets $?." --ruby 2.2.1 docs
110 unless $?.exitstatus == 0
111 raise GitCommandError.new("`git #{gitcmd.join ' '}` #{$?}: #{output}")
116 class GitCommandError < StandardError