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



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

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



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

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)


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

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

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



174
175
176
177
178
179
180
181
182
# File 'lib/dapp/dimg/git_repo/base.rb', line 174

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)


238
239
240
# File 'lib/dapp/dimg/git_repo/base.rb', line 238

def empty?
  git.empty?
end

#exclude_pathsObject



27
28
29
# File 'lib/dapp/dimg/git_repo/base.rb', line 27

def exclude_paths
  []
end

#find_commit_id_by_message(regex) ⇒ Object



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

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

#get_ruby2go_state_hashObject



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

def get_ruby2go_state_hash
  {
    "Dapp" => dapp.get_ruby2go_state_hash,
    "Name" => @name.to_s,
  }
end

#head_commitObject



188
189
190
# File 'lib/dapp/dimg/git_repo/base.rb', line 188

def head_commit
  git.head.target_id
end

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

Returns:

  • (Boolean)


160
161
162
# File 'lib/dapp/dimg/git_repo/base.rb', line 160

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



192
193
194
# File 'lib/dapp/dimg/git_repo/base.rb', line 192

def latest_branch_commit(_)
  raise
end

#latest_tag_commit(_) ⇒ Object



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

def latest_tag_commit(_)
  raise
end

#lookup_commit(commit) ⇒ Object



234
235
236
# File 'lib/dapp/dimg/git_repo/base.rb', line 234

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

#lookup_object(oid) ⇒ Object



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

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

#nested_git_directories_patches(*_args) ⇒ Object



58
59
60
# File 'lib/dapp/dimg/git_repo/base.rb', line 58

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: примеров использования.



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

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



121
122
123
# File 'lib/dapp/dimg/git_repo/base.rb', line 121

def raise_submodule_commit_not_found!(_)
  raise
end

#remote_branchesObject



210
211
212
213
214
215
# File 'lib/dapp/dimg/git_repo/base.rb', line 210

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



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/dapp/dimg/git_repo/base.rb', line 31

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



54
55
56
# File 'lib/dapp/dimg/git_repo/base.rb', line 54

def remote_origin_url_protocol
  url_protocol(remote_origin_url)
end

#set_ruby2go_state_hash(state) ⇒ Object



23
24
25
# File 'lib/dapp/dimg/git_repo/base.rb', line 23

def set_ruby2go_state_hash(state)
  @name = state["Name"]
end

#submodule_params(submodule) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/dapp/dimg/git_repo/base.rb', line 67

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



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/dapp/dimg/git_repo/base.rb', line 125

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



90
91
92
93
94
95
96
97
# File 'lib/dapp/dimg/git_repo/base.rb', line 90

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



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/dapp/dimg/git_repo/base.rb', line 99

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



117
118
119
# File 'lib/dapp/dimg/git_repo/base.rb', line 117

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



62
63
64
65
# File 'lib/dapp/dimg/git_repo/base.rb', line 62

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



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

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

#tracked_remote_repository?Boolean

Returns:

  • (Boolean)


242
243
244
# File 'lib/dapp/dimg/git_repo/base.rb', line 242

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

#walkerObject



224
225
226
227
228
# File 'lib/dapp/dimg/git_repo/base.rb', line 224

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