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

#branchObject



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

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_at(commit) ⇒ Object



165
166
167
# File 'lib/dapp/dimg/git_repo/base.rb', line 165

def commit_at(commit)
  lookup_commit(commit).time.to_i
end

#commit_exists?(commit) ⇒ Boolean

Returns:

  • (Boolean)


135
136
137
# File 'lib/dapp/dimg/git_repo/base.rb', line 135

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

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



125
126
127
128
129
130
131
132
133
# File 'lib/dapp/dimg/git_repo/base.rb', line 125

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

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



115
116
117
118
119
120
121
122
123
# File 'lib/dapp/dimg/git_repo/base.rb', line 115

def entries(commit, paths: [], exclude_paths: [])
  [].tap do |entries|
    lookup_commit(commit).tree.walk(:preorder) do |root, entry|
      fullpath = File.join(root, entry[:name]).reverse.chomp('/').reverse
      next if entry[:type] == :tree || ignore_path?(fullpath, paths: paths, exclude_paths: exclude_paths)
      entries << [root, entry]
    end
  end
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



169
170
171
172
173
174
# File 'lib/dapp/dimg/git_repo/base.rb', line 169

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

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

Returns:

  • (Boolean)


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

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

#latest_commit(_branch) ⇒ Object



139
140
141
# File 'lib/dapp/dimg/git_repo/base.rb', line 139

def latest_commit(_branch)
  raise
end

#lookup_commit(commit) ⇒ Object



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

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

#lookup_object(oid) ⇒ Object



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

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



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

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

#remote_branchesObject



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

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_url(gitsubmodule_url) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/dapp/dimg/git_repo/base.rb', line 76

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_params(commit, paths: [], exclude_paths: []) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
# File 'lib/dapp/dimg/git_repo/base.rb', line 51

def submodules_params(commit, paths: [], exclude_paths: [])
  raise "Workdir not supported for #{self.class}" if commit.nil?

  entry = begin
    lookup_commit(commit).tree.path('.gitmodules')
  rescue Rugged::TreeError
    return []
  end

  submodules_params_base(lookup_object(entry[:oid]).content, paths: paths, exclude_paths: exclude_paths)
end

#submodules_params_base(gitsubmodule_content, paths: [], exclude_paths: []) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/dapp/dimg/git_repo/base.rb', line 63

def submodules_params_base(gitsubmodule_content, paths: [], exclude_paths: [])
  IniFile.new.parse(gitsubmodule_content)
    .to_h
    .select { |_, params| !ignore_directory?(params['path'], paths: paths, exclude_paths: exclude_paths) }
    .map do |_, params|
      params = params.symbolize_keys
      params[:branch] = params[:branch].to_s if params.key?(:branch)
      params[:url] = submodule_url(params[:url])
      params[:type] = url_protocol(params[:url]) == :noname ? :local : :remote
      params
    end
end

#tag_at(name) ⇒ Object



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

def tag_at(name)
  tag = git.tags.find { |t| t.name == name }
  tag.target.time.to_i
end

#tagsObject



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

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

#walkerObject



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

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