Class: Dapp::Dimg::GitRepo::Base

Inherits:
Object
  • Object
show all
Includes:
Helper::Trivia
Defined in:
lib/dapp/dimg/git_repo/base.rb

Overview

Base class for any Git repo (remote, gitkeeper, etc)

Direct Known Subclasses

Local, Remote

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helper::Trivia

#check_path?, #check_subpath?, #class_to_lowercase, class_to_lowercase, #delete_file, #ignore_path?, #ignore_path_base, #kwargs, #make_path, #path_checker, #search_file_upward

Constructor Details

#initialize(dapp, name) ⇒ Base

Returns a new instance of Base.



11
12
13
14
# File 'lib/dapp/dimg/git_repo/base.rb', line 11

def initialize(dapp, name)
  @dapp = dapp
  @name = name
end

Instance Attribute Details

#dappObject (readonly)

Returns the value of attribute dapp.



9
10
11
# File 'lib/dapp/dimg/git_repo/base.rb', line 9

def dapp
  @dapp
end

#nameObject (readonly)

Returns the value of attribute name.



8
9
10
# File 'lib/dapp/dimg/git_repo/base.rb', line 8

def name
  @name
end

Instance Method Details

#blobs_entries(commit, paths: [], exclude_paths: []) ⇒ Object



153
154
155
156
157
158
159
160
161
# File 'lib/dapp/dimg/git_repo/base.rb', line 153

def blobs_entries(commit, paths: [], exclude_paths: [])
  [].tap do |entries|
    lookup_commit(commit).tree.walk_blobs(:preorder) do |root, entry|
      fullpath = File.join(root, entry[:name]).reverse.chomp('/').reverse
      next if ignore_path?(fullpath, paths: paths, exclude_paths: exclude_paths)
      entries << [root, entry]
    end
  end
end

#branchObject



189
190
191
192
193
# File 'lib/dapp/dimg/git_repo/base.rb', line 189

def branch
  git.head.name.sub(/^refs\/heads\//, '')
rescue Rugged::ReferenceError => e
  raise Error::Rugged, code: :git_repository_reference_error, data: { name: name, message: e.message.downcase }
end

#commit_exists?(commit) ⇒ Boolean

Returns:

  • (Boolean)


173
174
175
# File 'lib/dapp/dimg/git_repo/base.rb', line 173

def commit_exists?(commit)
  git.exists?(commit)
end

#diff(from, to, **kwargs) ⇒ Object



163
164
165
166
167
168
169
170
171
# File 'lib/dapp/dimg/git_repo/base.rb', line 163

def diff(from, to, **kwargs)
  if to.nil?
    raise "Workdir diff not supported for #{self.class}"
  elsif from.nil?
    Rugged::Tree.diff(git, nil, to, **kwargs)
  else
    lookup_commit(from).diff(lookup_commit(to), **kwargs)
  end
end

#empty?Boolean

Returns:

  • (Boolean)


227
228
229
# File 'lib/dapp/dimg/git_repo/base.rb', line 227

def empty?
  git.empty?
end

#exclude_pathsObject



16
17
18
# File 'lib/dapp/dimg/git_repo/base.rb', line 16

def exclude_paths
  []
end

#find_commit_id_by_message(regex) ⇒ Object



206
207
208
209
210
211
# File 'lib/dapp/dimg/git_repo/base.rb', line 206

def find_commit_id_by_message(regex)
  walker.each do |commit|
    msg = commit.message.encode('UTF-8', invalid: :replace, undef: :replace)
    return commit.oid if msg =~ regex
  end
end

#head_commitObject



177
178
179
# File 'lib/dapp/dimg/git_repo/base.rb', line 177

def head_commit
  git.head.target_id
end

#ignore_patch?(patch, paths: [], exclude_paths: []) ⇒ Boolean

Returns:

  • (Boolean)


149
150
151
# File 'lib/dapp/dimg/git_repo/base.rb', line 149

def ignore_patch?(patch, paths: [], exclude_paths: [])
  ignore_path?(patch.delta.new_file[:path], paths: paths, exclude_paths: exclude_paths)
end

#latest_branch_commit(_) ⇒ Object



181
182
183
# File 'lib/dapp/dimg/git_repo/base.rb', line 181

def latest_branch_commit(_)
  raise
end

#latest_tag_commit(_) ⇒ Object



185
186
187
# File 'lib/dapp/dimg/git_repo/base.rb', line 185

def latest_tag_commit(_)
  raise
end

#lookup_commit(commit) ⇒ Object



223
224
225
# File 'lib/dapp/dimg/git_repo/base.rb', line 223

def lookup_commit(commit)
  git.lookup(commit)
end

#lookup_object(oid) ⇒ Object



219
220
221
# File 'lib/dapp/dimg/git_repo/base.rb', line 219

def lookup_object(oid)
  git.lookup(oid)
end

#nested_git_directories_patches(*_args) ⇒ Object



47
48
49
# File 'lib/dapp/dimg/git_repo/base.rb', line 47

def nested_git_directories_patches(*_args)
  raise
end

#patches(from, to, paths: [], exclude_paths: [], **kwargs) ⇒ Object

FIXME: Убрать логику исключения путей exclude_paths из данного класса, FIXME: т.к. большинство методов не поддерживают инвариант FIXME “всегда выдавать данные с исключенными путями”. FIXME: Например, метод diff выдает данные без учета exclude_paths. FIXME: Лучше перенести фильтрацию в GitArtifact::diff_patches. FIXME: ИЛИ обеспечить этот инвариант, но это ограничит в возможностях FIXME: использование Rugged извне этого класса и это более сложный путь. FIXME: Лучше сейчас убрать фильтрацию, а добавить ее когда наберется достаточно FIXME: примеров использования.



143
144
145
146
147
# File 'lib/dapp/dimg/git_repo/base.rb', line 143

def patches(from, to, paths: [], exclude_paths: [], **kwargs)
  diff(from, to, **kwargs).patches.select do |patch|
    !ignore_patch?(patch, paths: paths, exclude_paths: exclude_paths)
  end
end

#raise_submodule_commit_not_found!(_) ⇒ Object



110
111
112
# File 'lib/dapp/dimg/git_repo/base.rb', line 110

def raise_submodule_commit_not_found!(_)
  raise
end

#remote_branchesObject



199
200
201
202
203
204
# File 'lib/dapp/dimg/git_repo/base.rb', line 199

def remote_branches
  git.branches
    .map(&:name)
    .select { |b| b.start_with?('origin/') }
    .map { |b| b.reverse.chomp('origin/'.reverse).reverse }
end

#remote_origin_urlObject



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/dapp/dimg/git_repo/base.rb', line 20

def remote_origin_url
  @remote_origin_url ||= begin
    ro_url = url
    while url_protocol(ro_url) == :noname
      begin
        parent_git = Rugged::Repository.discover(ro_url)
      rescue Rugged::OSError
        parent_git_path = parent_git ? parent_git.path : path
        raise Error::Rugged, code: :git_repository_not_found, data: { path: ro_url, parent_git_path: parent_git_path }
      end

      ro_url = begin
        git_url(parent_git)
      rescue Error::Rugged => e
        break if e.net_status[:code] == :git_repository_without_remote_url # local repository
        raise
      end
    end

    ro_url
  end
end

#remote_origin_url_protocolObject



43
44
45
# File 'lib/dapp/dimg/git_repo/base.rb', line 43

def remote_origin_url_protocol
  url_protocol(remote_origin_url)
end

#submodule_params(submodule) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/dapp/dimg/git_repo/base.rb', line 56

def submodule_params(submodule)
  {}.tap do |params|
    params[:path]   = submodule.path
    params[:url]    = begin
      params_url = submodule_url(submodule.url)
      params_url = "#{params_url}.git" if url_protocol(params[:url]) != :noname && !params_url.end_with?('.git')
      params_url
    end # https://github.com/libgit2/rugged/issues/761

    params[:type] = begin
      if url_protocol(params[:url]) == :noname
        submodule_absolute_path = File.join(File.dirname(path), params[:path])
        dapp.log_warning(desc: { code: :submodule_url_scheme_not_detected,
                                 data: { url: params[:url], path: submodule_absolute_path } })
        :local
      else
        :remote
      end
    end
    params[:commit] = submodule.head_oid
  end
end

#submodule_url(gitsubmodule_url) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/dapp/dimg/git_repo/base.rb', line 114

def submodule_url(gitsubmodule_url)
  if gitsubmodule_url.start_with?('../')
    case remote_origin_url_protocol
    when :http, :https, :git
      uri = URI.parse(remote_origin_url)
      uri.path = File.expand_path(File.join(uri.path, gitsubmodule_url))
      uri.to_s
    when :ssh
      host_with_user, group_and_project = remote_origin_url.split(':', 2)
      group_and_project = File.expand_path(File.join('/', group_and_project, gitsubmodule_url))[1..-1]
      [host_with_user, group_and_project].join(':')
    else
      raise
    end
  else
    gitsubmodule_url
  end
end

#submodules(commit, paths: [], exclude_paths: []) ⇒ Object



79
80
81
82
83
84
85
86
# File 'lib/dapp/dimg/git_repo/base.rb', line 79

def submodules(commit, paths: [], exclude_paths: [])
  Rugged::SubmoduleCollection.new(submodules_git(commit)).select do |submodule|
    next false if ignore_directory?(submodule.path, paths: paths, exclude_paths: exclude_paths)
    next true  if submodule.in_config?
    dapp.log_warning(desc: { code: :submodule_mapping_not_found,
                             data: { path: submodule.path, repo: name } })
  end
end

#submodules_git(commit) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/dapp/dimg/git_repo/base.rb', line 88

def submodules_git(commit)
  submodules_git_path(commit).tap do |git_path|
    break begin
      if git_path.directory?
        Rugged::Repository.new(git_path.to_s)
      else
        Rugged::Repository.clone_at(path.to_s, git_path.to_s).tap do |submodules_git|
          begin
            submodules_git.checkout(commit, strategy: :force)
          rescue Rugged::ReferenceError
            raise_submodule_commit_not_found!(commit)
          end
        end
      end
    end
  end
end

#submodules_git_path(commit) ⇒ Object



106
107
108
# File 'lib/dapp/dimg/git_repo/base.rb', line 106

def submodules_git_path(commit)
  Pathname(File.join(dapp.host_docker_tmp_config_dir, "submodule", dapp.consistent_uniq_slugify(name), commit).to_s)
end

#submodules_params(commit, paths: [], exclude_paths: []) ⇒ Object



51
52
53
54
# File 'lib/dapp/dimg/git_repo/base.rb', line 51

def submodules_params(commit, paths: [], exclude_paths: [])
  raise "Workdir not supported for `#{self.class}` repository" if commit.nil?
  submodules(commit, paths: paths, exclude_paths: exclude_paths).map(&method(:submodule_params))
end

#tagsObject



195
196
197
# File 'lib/dapp/dimg/git_repo/base.rb', line 195

def tags
  git.tags.map(&:name)
end

#tracked_remote_repository?Boolean

Returns:

  • (Boolean)


231
232
233
# File 'lib/dapp/dimg/git_repo/base.rb', line 231

def tracked_remote_repository?
  !git.remotes.to_a.empty?
end

#walkerObject



213
214
215
216
217
# File 'lib/dapp/dimg/git_repo/base.rb', line 213

def walker
  walker = Rugged::Walker.new(git)
  walker.push(git.head.target_id)
  walker
end