dapp 0.24.3 → 0.24.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/config/en/net_status.yml +5 -2
- data/lib/dapp.rb +2 -0
- data/lib/dapp/dapp.rb +4 -1
- data/lib/dapp/dimg/build/stage/artifact_base.rb +2 -3
- data/lib/dapp/dimg/config/directive/artifact_dimg.rb +0 -7
- data/lib/dapp/dimg/config/directive/dimg/instance_methods.rb +1 -0
- data/lib/dapp/dimg/config/directive/dimg/validation.rb +47 -10
- data/lib/dapp/dimg/dapp/command/build.rb +1 -1
- data/lib/dapp/dimg/dapp/command/build_context/export.rb +1 -1
- data/lib/dapp/dimg/dapp/command/common.rb +1 -3
- data/lib/dapp/dimg/dapp/command/run.rb +1 -1
- data/lib/dapp/dimg/dapp/command/stage_image.rb +1 -1
- data/lib/dapp/dimg/dapp/command/stages/common.rb +1 -1
- data/lib/dapp/dimg/dapp/dapp.rb +1 -0
- data/lib/dapp/dimg/dapp/dimg.rb +15 -0
- data/lib/dapp/dimg/dimg/git_artifact.rb +6 -5
- data/lib/dapp/dimg/git_artifact.rb +66 -44
- data/lib/dapp/dimg/git_repo/base.rb +30 -14
- data/lib/dapp/dimg/git_repo/local.rb +95 -0
- data/lib/dapp/dimg/git_repo/own.rb +6 -52
- data/lib/dapp/kube/dapp/command/deploy.rb +9 -4
- data/lib/dapp/kube/helm/release.rb +4 -2
- data/lib/dapp/kube/helm/values.rb +1 -1
- data/lib/dapp/kube/kubernetes/client/resource/pod.rb +14 -0
- data/lib/dapp/kube/kubernetes/manager/container.rb +1 -1
- data/lib/dapp/kube/kubernetes/manager/deployment.rb +9 -29
- data/lib/dapp/kube/kubernetes/manager/pod.rb +36 -2
- data/lib/dapp/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9a285aead0a2e57006e54a0839ab32cf4170529
|
4
|
+
data.tar.gz: cd58972b2de67689e2173bffe9524a0623e79bc1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9dbb053e622ce8ac204b9529dbf2c1ca266b22a4f46fec3736963861b5e74148ff19f423e297c1a3a9d0fd44afeeb787c3a448978ab2d0219273a23448eca36f
|
7
|
+
data.tar.gz: f15547e0e17c93ba3e39ec915a1413b6445392212c9779333aa9d6742888b86d1291ee6d4be3f830dc79a21fe7af88001b32a428fbf64111da2d58eba3842772
|
data/config/en/net_status.yml
CHANGED
@@ -44,6 +44,7 @@ en:
|
|
44
44
|
expected_only_one_tag: 'Expected only one tag (`%{tags}`)!'
|
45
45
|
kube_deploy_timeout: "Deploy timeout!"
|
46
46
|
kube_connect_timeout: "Connect timeout when connecting to kube API."
|
47
|
+
kube_helm_failed: "Helm failed: %{output}"
|
47
48
|
dapp:
|
48
49
|
no_such_dimg: "No such dimg: `%{dimgs_patterns}`!"
|
49
50
|
no_such_app: "No such app: `%{apps_patterns}`!"
|
@@ -80,7 +81,7 @@ en:
|
|
80
81
|
stage_artifact_double_associate: "Can't use `%{stage}` stage for artifact; already used in `%{conflict_stage}` stage!"
|
81
82
|
stage_artifact_not_supported_associated_stage: "Bad artifact stage `%{stage}`!"
|
82
83
|
git_artifact_remote_branch_with_commit: "Remote git repo: use `commit` or `branch` directive!"
|
83
|
-
artifact_conflict: "Conflict between artifacts
|
84
|
+
artifact_conflict: "Conflict between artifacts!\n\n%{dappfile_context}"
|
84
85
|
scratch_unsupported_directive: "Scratch dimg has unsupported directive `%{directive}`!"
|
85
86
|
scratch_artifact_required: "Scratch dimg without artifacts!"
|
86
87
|
scratch_artifact_associated: "Scratch artifact can't be associated: not expected `before`/`after` attribute!"
|
@@ -115,7 +116,7 @@ en:
|
|
115
116
|
rugged:
|
116
117
|
git_repository_reference_error: "Git repo `%{name}`: %{message}!"
|
117
118
|
rugged_remote_error: "Remote git repo `%{url}`: `%{message}`!"
|
118
|
-
local_git_repository_does_not_exist: "Local git repo: doesn't exist!"
|
119
|
+
local_git_repository_does_not_exist: "Local git repo (`%{path}`): doesn't exist!"
|
119
120
|
commit_not_found_in_local_git_repository: "Local git repo: commit `%{commit}` not found!\nIf commit has been rebased: run command `dapp dimg stages cleanup local --improper-git-commit`!"
|
120
121
|
commit_not_found_in_remote_git_repository: "Remote git repo `%{url}`: commit `%{commit}` not found!\nIf commit has been rebased: run command `dapp dimg stages cleanup local --improper-git-commit`!"
|
121
122
|
branch_not_exist_in_remote_git_repository: "Remote git repo `%{url}`: branch `%{branch}` not exist!"
|
@@ -136,6 +137,8 @@ en:
|
|
136
137
|
server_connection_refused: "Kube server `%{url}` connection refused: %{error}"
|
137
138
|
server_error: "Kube respond with server error code %{response_http_status}, request parameters: `%{request_parameters}`, response: `%{response_raw_body}`"
|
138
139
|
container_stuck: "Pod's `%{pod_name}` container `%{container_name}` stuck in %{state} state: %{state_reason}: %{state_message}"
|
140
|
+
bad_image: "Pod `%{pod_name}` bad image: %{reason}: %{message}"
|
141
|
+
container_crash: "Pod's `%{pod_name}` container crashed: %{reason}: %{message}"
|
139
142
|
secret:
|
140
143
|
bad_data: "Data `%{data}` can't be decrypted: check encryption key and data!"
|
141
144
|
key_length_too_short: "Encryption key isn't valid (required size %{required_size} bytes)!"
|
data/lib/dapp.rb
CHANGED
@@ -232,6 +232,7 @@ require 'dapp/dimg/dapp/command/build_context/export'
|
|
232
232
|
require 'dapp/dimg/dapp/command/build_context/import'
|
233
233
|
require 'dapp/dimg/dapp/command/build_context/common'
|
234
234
|
require 'dapp/dimg/dapp/dappfile'
|
235
|
+
require 'dapp/dimg/dapp/dimg'
|
235
236
|
require 'dapp/dimg/dapp/dapp'
|
236
237
|
require 'dapp/dimg/docker_registry'
|
237
238
|
require 'dapp/dimg/docker_registry/base/request'
|
@@ -254,6 +255,7 @@ require 'dapp/dimg/lock/base'
|
|
254
255
|
require 'dapp/dimg/lock/file'
|
255
256
|
require 'dapp/dimg/filelock'
|
256
257
|
require 'dapp/dimg/git_repo/base'
|
258
|
+
require 'dapp/dimg/git_repo/local'
|
257
259
|
require 'dapp/dimg/git_repo/own'
|
258
260
|
require 'dapp/dimg/git_repo/remote'
|
259
261
|
require 'dapp/dimg/git_artifact'
|
data/lib/dapp/dapp.rb
CHANGED
@@ -71,11 +71,14 @@ module Dapp
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def git_own_repo_exist?
|
74
|
-
git_own_repo.
|
74
|
+
!git_own_repo.nil?
|
75
75
|
end
|
76
76
|
|
77
77
|
def git_own_repo
|
78
78
|
@git_own_repo ||= Dimg::GitRepo::Own.new(self)
|
79
|
+
rescue Dimg::Error::Rugged => e
|
80
|
+
raise unless e.net_status[:code] == :local_git_repository_does_not_exist
|
81
|
+
nil
|
79
82
|
end
|
80
83
|
|
81
84
|
def path(*path)
|
@@ -22,9 +22,8 @@ module Dapp
|
|
22
22
|
def artifacts
|
23
23
|
@artifacts ||= begin
|
24
24
|
dimg.config.public_send("_#{name}").map do |artifact|
|
25
|
-
artifact_dimg =
|
26
|
-
|
27
|
-
ignore_git_fetch: dimg.ignore_git_fetch)
|
25
|
+
artifact_dimg = dimg.dapp.artifact_dimg(config: artifact._config,
|
26
|
+
ignore_git_fetch: dimg.ignore_git_fetch)
|
28
27
|
{ name: artifact._config._name, options: artifact._artifact_options, dimg: artifact_dimg }
|
29
28
|
end
|
30
29
|
end
|
@@ -71,12 +71,39 @@ module Dapp
|
|
71
71
|
verifiable_artifact = artifacts.shift
|
72
72
|
artifacts.select { |a| a[:to] == verifiable_artifact[:to] }.each do |artifact|
|
73
73
|
next if verifiable_artifact[:index] == artifact[:index]
|
74
|
-
|
75
|
-
|
74
|
+
begin
|
75
|
+
validate_artifact!(verifiable_artifact, artifact)
|
76
|
+
validate_artifact!(artifact, verifiable_artifact)
|
77
|
+
rescue ::Dapp::Error::Config => e
|
78
|
+
conflict_between_artifacts!(artifact, verifiable_artifact) if e.net_status[:code] == :artifact_conflict
|
79
|
+
raise
|
80
|
+
end
|
76
81
|
end
|
77
82
|
end
|
78
83
|
end
|
79
84
|
|
85
|
+
def conflict_between_artifacts!(*formatted_artifacts)
|
86
|
+
artifacts = formatted_artifacts.flatten.map { |formatted_artifact| formatted_artifact[:related_artifact] }
|
87
|
+
dappfile_context = artifacts.map do |artifact|
|
88
|
+
artifact_directive = []
|
89
|
+
artifact_directive << begin
|
90
|
+
if artifact.is_a? Artifact::Export
|
91
|
+
"artifact.export('#{artifact._cwd}') do"
|
92
|
+
else
|
93
|
+
"git#{"('#{artifact._url}')" if artifact.respond_to?(:_url)}.add('#{artifact._cwd}') do"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
[:include_paths, :exclude_paths].each do |directive|
|
97
|
+
next if (paths = artifact.send("_#{directive}")).empty?
|
98
|
+
artifact_directive << " #{directive} '#{paths.join("', '")}'"
|
99
|
+
end
|
100
|
+
artifact_directive << " to '#{artifact._to}'"
|
101
|
+
artifact_directive << 'end'
|
102
|
+
artifact_directive.join("\n")
|
103
|
+
end.join("\n\n")
|
104
|
+
raise ::Dapp::Error::Config, code: :artifact_conflict, data: { dappfile_context: dappfile_context }
|
105
|
+
end
|
106
|
+
|
80
107
|
def validate_artifact_format(artifacts)
|
81
108
|
artifacts.map do |a|
|
82
109
|
path_format = proc { |path| File.expand_path(File.join('/', path, '/'))[1..-1] }
|
@@ -104,7 +131,8 @@ module Dapp
|
|
104
131
|
index: artifacts.index(a),
|
105
132
|
to: to,
|
106
133
|
include_paths: include_paths,
|
107
|
-
exclude_paths: exclude_paths
|
134
|
+
exclude_paths: exclude_paths,
|
135
|
+
related_artifact: a
|
108
136
|
}
|
109
137
|
end
|
110
138
|
end
|
@@ -113,17 +141,26 @@ module Dapp
|
|
113
141
|
verifiable_artifact[:include_paths].each do |verifiable_path|
|
114
142
|
potential_conflicts = artifact[:include_paths].select { |path| path.start_with?(verifiable_path) }
|
115
143
|
validate_artifact_path!(verifiable_artifact, potential_conflicts)
|
116
|
-
end
|
117
|
-
|
144
|
+
end
|
145
|
+
|
146
|
+
if verifiable_artifact[:include_paths].empty?
|
147
|
+
if artifact[:include_paths].empty? || verifiable_artifact[:exclude_paths].empty?
|
148
|
+
raise ::Dapp::Error::Config, code: :artifact_conflict
|
149
|
+
else
|
150
|
+
validate_artifact_path!(verifiable_artifact, artifact[:include_paths])
|
151
|
+
end
|
152
|
+
end
|
118
153
|
end
|
119
154
|
|
120
155
|
def validate_artifact_path!(verifiable_artifact, potential_conflicts)
|
121
|
-
|
122
|
-
|
123
|
-
|
156
|
+
raise ::Dapp::Error::Config, code: :artifact_conflict unless begin
|
157
|
+
potential_conflicts.all? do |path|
|
158
|
+
loop do
|
159
|
+
break if verifiable_artifact[:exclude_paths].include?(path) || ((path = File.dirname(path)) == '.')
|
160
|
+
end
|
161
|
+
verifiable_artifact[:exclude_paths].include?(path)
|
124
162
|
end
|
125
|
-
|
126
|
-
end.tap { |res| res || raise(::Dapp::Error::Config, code: :artifact_conflict) }
|
163
|
+
end
|
127
164
|
end
|
128
165
|
|
129
166
|
def _associated_artifacts
|
@@ -14,7 +14,7 @@ module Dapp
|
|
14
14
|
def export_build_context_image_tar
|
15
15
|
lock("#{name}.images", readonly: true) do
|
16
16
|
context_images_names = build_configs.map do |config|
|
17
|
-
|
17
|
+
dimg(config: config, ignore_git_fetch: true).tagged_images.map(&:name)
|
18
18
|
end.flatten
|
19
19
|
|
20
20
|
log_secondary_process(:images, short: true) do
|
@@ -123,9 +123,7 @@ module Dapp
|
|
123
123
|
validate_repo_name!(repo)
|
124
124
|
build_configs.each do |config|
|
125
125
|
log_dimg_name_with_indent(config) do
|
126
|
-
|
127
|
-
yield dimg
|
128
|
-
end
|
126
|
+
yield dimg(config: config, ignore_git_fetch: true, should_be_built: should_be_built)
|
129
127
|
end
|
130
128
|
end
|
131
129
|
end
|
@@ -6,7 +6,7 @@ module Dapp
|
|
6
6
|
def run(docker_options, command)
|
7
7
|
one_dimg!
|
8
8
|
setup_ssh_agent
|
9
|
-
|
9
|
+
dimg(config: build_configs.first, ignore_git_fetch: true, should_be_built: true).run(docker_options, command)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -5,7 +5,7 @@ module Dapp
|
|
5
5
|
module StageImage
|
6
6
|
def stage_image
|
7
7
|
one_dimg!
|
8
|
-
puts
|
8
|
+
puts dimg(config: build_configs.first, ignore_git_fetch: true).stage_image_name(options[:stage])
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -56,7 +56,7 @@ module Dapp
|
|
56
56
|
def dapp_git_repositories
|
57
57
|
@dapp_git_repositories ||= begin
|
58
58
|
{}.tap do |repositories|
|
59
|
-
dimgs = build_configs.map { |config|
|
59
|
+
dimgs = build_configs.map { |config| dimg(config: config, ignore_git_fetch: true) }
|
60
60
|
dimgs.each do |dimg|
|
61
61
|
[dimg, dimg.artifacts]
|
62
62
|
.flatten
|
data/lib/dapp/dimg/dapp/dapp.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Dapp
|
2
|
+
module Dimg
|
3
|
+
module Dapp
|
4
|
+
module Dimg
|
5
|
+
def dimg(config:, **kwargs)
|
6
|
+
(@dimgs ||= {})[config._name] ||= ::Dapp::Dimg::Dimg.new(config: config, dapp: self, **kwargs)
|
7
|
+
end
|
8
|
+
|
9
|
+
def artifact_dimg(config:, **kwargs)
|
10
|
+
(@artifacts_dimgs ||= {})[config._name] ||= ::Dapp::Dimg::Artifact.new(config: config, dapp: self, **kwargs)
|
11
|
+
end
|
12
|
+
end # Dimg
|
13
|
+
end # Dapp
|
14
|
+
end # Dimg
|
15
|
+
end # Dapp
|
@@ -8,8 +8,9 @@ module Dapp
|
|
8
8
|
|
9
9
|
def local_git_artifacts
|
10
10
|
@local_git_artifact_list ||= [].tap do |artifacts|
|
11
|
+
break artifacts if (local_git_artifacts = Array(config._git_artifact._local)).empty?
|
11
12
|
repo = GitRepo::Own.new(self)
|
12
|
-
|
13
|
+
local_git_artifacts.map do |ga_config|
|
13
14
|
artifacts.concat(generate_git_artifacts(repo, **ga_config._artifact_options))
|
14
15
|
end
|
15
16
|
end
|
@@ -27,14 +28,14 @@ module Dapp
|
|
27
28
|
def generate_git_artifacts(repo, **git_artifact_options)
|
28
29
|
[].tap do |artifacts|
|
29
30
|
artifacts << (artifact = ::Dapp::Dimg::GitArtifact.new(repo, **git_artifact_options))
|
30
|
-
artifacts.concat(
|
31
|
+
artifacts.concat(generate_git_embedded_artifacts(artifact))
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
34
|
-
def
|
35
|
+
def generate_git_embedded_artifacts(artifact)
|
35
36
|
[].tap do |artifacts|
|
36
|
-
artifacts.concat(submodules_artifacts = artifact.
|
37
|
-
artifacts.concat(submodules_artifacts.map(&method(:
|
37
|
+
artifacts.concat(submodules_artifacts = artifact.embedded_artifacts)
|
38
|
+
artifacts.concat(submodules_artifacts.map(&method(:generate_git_embedded_artifacts)).flatten)
|
38
39
|
end
|
39
40
|
end
|
40
41
|
end # GitArtifact
|
@@ -33,6 +33,10 @@ module Dapp
|
|
33
33
|
end
|
34
34
|
# rubocop:enable Metrics/ParameterLists
|
35
35
|
|
36
|
+
def embedded_artifacts
|
37
|
+
[submodules_artifacts, nested_git_directory_artifacts].flatten
|
38
|
+
end
|
39
|
+
|
36
40
|
def submodules_artifacts
|
37
41
|
commit = dev_mode? ? nil : latest_commit
|
38
42
|
repo.submodules_params(commit,
|
@@ -41,65 +45,72 @@ module Dapp
|
|
41
45
|
end
|
42
46
|
|
43
47
|
def submodule_artifact(submodule_params)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
rescue Rugged::InvalidError => e
|
49
|
-
raise Error::Rugged, code: :incorrect_gitmodules_file, data: { error: e.message }
|
50
|
-
end
|
48
|
+
embedded_artifact(submodule_params)
|
49
|
+
rescue Rugged::InvalidError => e
|
50
|
+
raise Error::Rugged, code: :incorrect_gitmodules_file, data: { error: e.message }
|
51
|
+
end
|
51
52
|
|
52
|
-
|
53
|
+
def nested_git_directory_artifacts
|
54
|
+
return [] unless dev_mode?
|
55
|
+
repo
|
56
|
+
.nested_git_directories_patches(paths: include_paths_or_cwd, exclude_paths: exclude_paths(true), **diff_patches_options)
|
57
|
+
.map(&method(:nested_git_directory_artifact))
|
53
58
|
end
|
54
59
|
|
55
|
-
def
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
60
|
+
def nested_git_directory_artifact(patch)
|
61
|
+
params = {}.tap do |p|
|
62
|
+
p[:path] = patch.delta.new_file[:path]
|
63
|
+
p[:type] = :local
|
64
|
+
end
|
65
|
+
embedded_artifact(params)
|
66
|
+
end
|
67
|
+
|
68
|
+
def embedded_artifact(embedded_params)
|
69
|
+
embedded_rel_path = embedded_params[:path]
|
70
|
+
embedded_repo = begin
|
71
|
+
if embedded_params[:type] == :remote
|
72
|
+
GitRepo::Remote.new(repo.dimg, embedded_rel_path,
|
73
|
+
url: embedded_params[:url]).tap { |r| r.fetch!(embedded_params[:branch]) }
|
74
|
+
elsif embedded_params[:type] == :local
|
75
|
+
embedded_path = File.join(repo.workdir_path, embedded_params[:path])
|
76
|
+
GitRepo::Local.new(repo.dimg, embedded_rel_path, embedded_path)
|
66
77
|
else
|
67
78
|
raise
|
68
79
|
end
|
69
|
-
else
|
70
|
-
url
|
71
80
|
end
|
81
|
+
|
82
|
+
self.class.new(embedded_repo, embedded_artifact_options(embedded_params))
|
72
83
|
end
|
73
84
|
|
74
|
-
def
|
75
|
-
|
85
|
+
def embedded_artifact_options(embedded_params)
|
86
|
+
embedded_rel_path = embedded_params[:path]
|
76
87
|
|
77
88
|
{}.tap do |options|
|
78
|
-
options[:name] = repo.dapp.consistent_uniq_slugify("
|
79
|
-
options[:cwd] =
|
80
|
-
options[:to] = File.join(to,
|
81
|
-
options[:include_paths] =
|
82
|
-
options[:exclude_paths] =
|
89
|
+
options[:name] = repo.dapp.consistent_uniq_slugify("embedded-#{embedded_rel_path}")
|
90
|
+
options[:cwd] = embedded_inherit_path(cwd, embedded_rel_path).last
|
91
|
+
options[:to] = File.join(to, embedded_rel_path)
|
92
|
+
options[:include_paths] = embedded_inherit_paths(include_paths, embedded_rel_path)
|
93
|
+
options[:exclude_paths] = embedded_inherit_paths(exclude_paths, embedded_rel_path)
|
83
94
|
options[:stages_dependencies] = begin
|
84
95
|
stages_dependencies
|
85
|
-
.map { |stage, paths| [stage,
|
96
|
+
.map { |stage, paths| [stage, embedded_inherit_paths(paths, embedded_rel_path)] }
|
86
97
|
.to_h
|
87
98
|
end
|
88
|
-
options[:branch] =
|
99
|
+
options[:branch] = embedded_params[:branch]
|
89
100
|
options[:owner] = owner
|
90
101
|
options[:group] = group
|
91
102
|
end
|
92
103
|
end
|
93
104
|
|
94
|
-
def
|
105
|
+
def embedded_inherit_paths(paths, embedded_rel_path)
|
95
106
|
paths
|
96
|
-
.select { |path| check_path?(
|
97
|
-
.map { |path|
|
107
|
+
.select { |path| check_path?(embedded_rel_path, path) || check_subpath?(embedded_rel_path, path) }
|
108
|
+
.map { |path| embedded_inherit_path(path, embedded_rel_path) }
|
98
109
|
.flatten
|
99
110
|
.compact
|
100
111
|
end
|
101
112
|
|
102
|
-
def
|
113
|
+
def embedded_inherit_path(path, embedded_rel_path)
|
103
114
|
path_parts = path.split('/')
|
104
115
|
test_path = nil
|
105
116
|
inherited_paths = []
|
@@ -107,7 +118,7 @@ module Dapp
|
|
107
118
|
last_part_path = path_parts.shift
|
108
119
|
test_path = [test_path, last_part_path].compact.join('/')
|
109
120
|
|
110
|
-
non_match = !File.fnmatch(test_path,
|
121
|
+
non_match = !File.fnmatch(test_path, embedded_rel_path, File::FNM_PATHNAME)
|
111
122
|
part_for_all = (last_part_path == '**')
|
112
123
|
|
113
124
|
if non_match || part_for_all
|
@@ -462,16 +473,23 @@ module Dapp
|
|
462
473
|
|
463
474
|
def diff_patches(from_commit, to_commit, paths: include_paths_or_cwd)
|
464
475
|
(@diff_patches ||= {})[[from_commit, to_commit, paths]] ||= begin
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
476
|
+
repo
|
477
|
+
.patches(from_commit, to_commit, paths: paths, exclude_paths: exclude_paths(true), **diff_patches_options)
|
478
|
+
.select do |patch|
|
479
|
+
file_mode = patch.delta.new_file[:mode]
|
480
|
+
!(submodule_mode?(file_mode) || # FIXME: https://github.com/libgit2/rugged/issues/727
|
481
|
+
nested_git_directory_mode?(file_mode))
|
470
482
|
end
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
486
|
+
def diff_patches_options
|
487
|
+
{}.tap do |opts|
|
488
|
+
opts[:force_text] = true
|
489
|
+
if dev_mode?
|
490
|
+
opts[:include_untracked] = true
|
491
|
+
opts[:recurse_untracked_dirs] = true
|
471
492
|
end
|
472
|
-
repo
|
473
|
-
.patches(from_commit, to_commit, paths: paths, exclude_paths: exclude_paths(true), **options)
|
474
|
-
.select { |patch| !submodule_mode?(patch.delta.new_file[:mode]) } # FIXME: https://github.com/libgit2/rugged/issues/727
|
475
493
|
end
|
476
494
|
end
|
477
495
|
|
@@ -479,6 +497,10 @@ module Dapp
|
|
479
497
|
mode == 0o160000
|
480
498
|
end
|
481
499
|
|
500
|
+
def nested_git_directory_mode?(mode)
|
501
|
+
mode == 0o040000
|
502
|
+
end
|
503
|
+
|
482
504
|
def include_paths_or_cwd
|
483
505
|
case
|
484
506
|
when !include_paths(true).empty? then include_paths(true)
|
@@ -530,7 +552,7 @@ module Dapp
|
|
530
552
|
end
|
531
553
|
|
532
554
|
def local?
|
533
|
-
repo.is_a? GitRepo::
|
555
|
+
repo.is_a? GitRepo::Local
|
534
556
|
end
|
535
557
|
end
|
536
558
|
end
|
@@ -63,6 +63,10 @@ module Dapp
|
|
63
63
|
url_protocol(remote_origin_url)
|
64
64
|
end
|
65
65
|
|
66
|
+
def nested_git_directories_patches(*_args)
|
67
|
+
raise
|
68
|
+
end
|
69
|
+
|
66
70
|
def submodules_params(commit, paths: [], exclude_paths: [])
|
67
71
|
raise "Workdir not supported for #{self.class}" if commit.nil?
|
68
72
|
|
@@ -82,10 +86,31 @@ module Dapp
|
|
82
86
|
.map do |_, params|
|
83
87
|
params = params.symbolize_keys
|
84
88
|
params[:branch] = params[:branch].to_s if params.key?(:branch)
|
89
|
+
params[:url] = submodule_url(params[:url])
|
90
|
+
params[:type] = url_protocol(params[:url]) == :noname ? :local : :remote
|
85
91
|
params
|
86
92
|
end
|
87
93
|
end
|
88
94
|
|
95
|
+
def submodule_url(gitsubmodule_url)
|
96
|
+
if gitsubmodule_url.start_with?('../')
|
97
|
+
case remote_origin_url_protocol
|
98
|
+
when :http, :https, :git
|
99
|
+
uri = URI.parse(remote_origin_url)
|
100
|
+
uri.path = File.expand_path(File.join(uri.path, gitsubmodule_url))
|
101
|
+
uri.to_s
|
102
|
+
when :ssh
|
103
|
+
host_with_user, group_and_project = remote_origin_url.split(':', 2)
|
104
|
+
group_and_project = File.expand_path(File.join('/', group_and_project, gitsubmodule_url))[1..-1]
|
105
|
+
[host_with_user, group_and_project].join(':')
|
106
|
+
else
|
107
|
+
raise
|
108
|
+
end
|
109
|
+
else
|
110
|
+
gitsubmodule_url
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
89
114
|
# FIXME: Убрать логику исключения путей exclude_paths из данного класса,
|
90
115
|
# FIXME: т.к. большинство методов не поддерживают инвариант
|
91
116
|
# FIXME "всегда выдавать данные с исключенными путями".
|
@@ -98,16 +123,14 @@ module Dapp
|
|
98
123
|
|
99
124
|
def patches(from, to, paths: [], exclude_paths: [], **kwargs)
|
100
125
|
diff(from, to, **kwargs).patches.select do |patch|
|
101
|
-
|
102
|
-
args = [delta_new_file[:path], paths: paths, exclude_paths: exclude_paths]
|
103
|
-
if delta_new_file[:mode] == 0o040000 # nested git repository in dev mode
|
104
|
-
!ignore_directory?(*args)
|
105
|
-
else
|
106
|
-
!ignore_path?(*args)
|
107
|
-
end
|
126
|
+
ignore_patch?(patch, paths: paths, exclude_paths: exclude_paths)
|
108
127
|
end
|
109
128
|
end
|
110
129
|
|
130
|
+
def ignore_patch?(patch, paths: [], exclude_paths: [])
|
131
|
+
!ignore_path?(patch.delta.new_file[:path], paths: paths, exclude_paths: exclude_paths)
|
132
|
+
end
|
133
|
+
|
111
134
|
def entries(commit, paths: [], exclude_paths: [])
|
112
135
|
[].tap do |entries|
|
113
136
|
lookup_commit(commit).tree.walk(:preorder) do |root, entry|
|
@@ -183,13 +206,6 @@ module Dapp
|
|
183
206
|
git.lookup(commit)
|
184
207
|
end
|
185
208
|
|
186
|
-
def exist?
|
187
|
-
git
|
188
|
-
true
|
189
|
-
rescue Rugged::OSError
|
190
|
-
false
|
191
|
-
end
|
192
|
-
|
193
209
|
protected
|
194
210
|
|
195
211
|
attr_reader :manager
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Dapp
|
2
|
+
module Dimg
|
3
|
+
module GitRepo
|
4
|
+
class Local < Base
|
5
|
+
attr_reader :path
|
6
|
+
|
7
|
+
def initialize(manager, name, path)
|
8
|
+
super(manager, name)
|
9
|
+
self.path = path
|
10
|
+
end
|
11
|
+
|
12
|
+
def path=(path)
|
13
|
+
@path ||= Pathname(Rugged::Repository.new(path).path)
|
14
|
+
rescue Rugged::RepositoryError, Rugged::OSError => _e
|
15
|
+
raise Error::Rugged, code: :local_git_repository_does_not_exist, data: { path: path }
|
16
|
+
end
|
17
|
+
|
18
|
+
def workdir_path
|
19
|
+
Pathname(git.workdir)
|
20
|
+
end
|
21
|
+
|
22
|
+
def nested_git_directories_patches(paths: [], exclude_paths: [], **kwargs)
|
23
|
+
patches(nil, nil, paths: paths, exclude_paths: exclude_paths, **kwargs).select do |patch|
|
24
|
+
delta_new_file = patch.delta.new_file
|
25
|
+
nested_git_repository_mode?(delta_new_file[:mode])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# NOTICE: Параметры {from: nil, to: nil} можно указать только для Own repo.
|
30
|
+
# NOTICE: Для Remote repo такой вызов не имеет смысла и это ошибка пользователя класса Remote.
|
31
|
+
|
32
|
+
def submodules_params(commit, paths: [], exclude_paths: [])
|
33
|
+
return super unless commit.nil?
|
34
|
+
return [] unless File.file?((gitmodules_file_path = File.join(workdir_path, '.gitmodules')))
|
35
|
+
|
36
|
+
submodules_params_base(File.read(gitmodules_file_path),
|
37
|
+
paths: paths,
|
38
|
+
exclude_paths: exclude_paths).each do |submodule_params|
|
39
|
+
submodule_path = File.join(workdir_path, submodule_params[:path])
|
40
|
+
if git_repo_exist?(submodule_path)
|
41
|
+
dapp.log_info("Using local submodule `#{submodule_path}`!")
|
42
|
+
submodule_params[:type] = :local
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def ignore_patch?(patch, paths: [], exclude_paths: [])
|
48
|
+
delta_new_file = patch.delta.new_file
|
49
|
+
args = [delta_new_file[:path], paths: paths, exclude_paths: exclude_paths]
|
50
|
+
if nested_git_repository_mode?(delta_new_file[:mode])
|
51
|
+
!ignore_directory?(*args)
|
52
|
+
else
|
53
|
+
!ignore_path?(*args)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def nested_git_repository_mode?(mode)
|
58
|
+
mode == 0o040000
|
59
|
+
end
|
60
|
+
|
61
|
+
def diff(from, to, **kwargs)
|
62
|
+
if from.nil? and to.nil?
|
63
|
+
mid_commit = latest_commit
|
64
|
+
diff_obj = super(nil, mid_commit, **kwargs)
|
65
|
+
diff_obj.merge! git.lookup(mid_commit).diff_workdir(**kwargs)
|
66
|
+
diff_obj
|
67
|
+
elsif to.nil?
|
68
|
+
git.lookup(from).diff_workdir(**kwargs)
|
69
|
+
else
|
70
|
+
super
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def latest_commit(_branch = nil)
|
75
|
+
git.head.target_id
|
76
|
+
end
|
77
|
+
|
78
|
+
def lookup_commit(commit)
|
79
|
+
super
|
80
|
+
rescue Rugged::OdbError, TypeError => _e
|
81
|
+
raise Error::Rugged, code: :commit_not_found_in_local_git_repository, data: { commit: commit }
|
82
|
+
end
|
83
|
+
|
84
|
+
protected
|
85
|
+
|
86
|
+
def git_repo_exist?(path)
|
87
|
+
Rugged::Repository.new(path)
|
88
|
+
true
|
89
|
+
rescue Rugged::RepositoryError, Rugged::OSError => _e
|
90
|
+
false
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -1,63 +1,17 @@
|
|
1
1
|
module Dapp
|
2
2
|
module Dimg
|
3
3
|
module GitRepo
|
4
|
-
class Own <
|
4
|
+
class Own < Local
|
5
5
|
def initialize(manager)
|
6
|
-
super(manager, 'own')
|
6
|
+
super(manager, 'own', nil)
|
7
7
|
end
|
8
8
|
|
9
|
-
def
|
10
|
-
dapp.
|
11
|
-
end
|
12
|
-
|
13
|
-
def workdir_path
|
14
|
-
Pathname(git.workdir)
|
15
|
-
end
|
16
|
-
|
17
|
-
def path
|
18
|
-
@path ||= Pathname(Rugged::Repository.discover(dapp.path.to_s).path)
|
19
|
-
rescue Rugged::RepositoryError => _e
|
20
|
-
raise Error::Rugged, code: :local_git_repository_does_not_exist
|
21
|
-
end
|
22
|
-
|
23
|
-
# NOTICE: Параметры {from: nil, to: nil} можно указать только для Own repo.
|
24
|
-
# NOTICE: Для Remote repo такой вызов не имеет смысла и это ошибка пользователя класса Remote.
|
25
|
-
|
26
|
-
def submodules_params(commit, paths: [], exclude_paths: [])
|
27
|
-
return super unless commit.nil?
|
28
|
-
return [] unless File.file?((gitmodules_file_path = File.join(workdir_path, '.gitmodules')))
|
29
|
-
|
30
|
-
submodules_params_base(File.read(gitmodules_file_path), paths: paths, exclude_paths: exclude_paths)
|
31
|
-
end
|
32
|
-
|
33
|
-
def diff(from, to, **kwargs)
|
34
|
-
if from.nil? and to.nil?
|
35
|
-
mid_commit = latest_commit
|
36
|
-
diff_obj = super(nil, mid_commit, **kwargs)
|
37
|
-
diff_obj.merge! git.lookup(mid_commit).diff_workdir(**kwargs)
|
38
|
-
diff_obj
|
39
|
-
elsif to.nil?
|
40
|
-
git.lookup(from).diff_workdir(**kwargs)
|
41
|
-
else
|
42
|
-
super
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def latest_commit(_branch = nil)
|
47
|
-
git.head.target_id
|
9
|
+
def path=(_)
|
10
|
+
super(dapp.path.to_s)
|
48
11
|
end
|
49
12
|
|
50
|
-
def
|
51
|
-
|
52
|
-
rescue Rugged::OdbError, TypeError => _e
|
53
|
-
raise Error::Rugged, code: :commit_not_found_in_local_git_repository, data: { commit: commit }
|
54
|
-
end
|
55
|
-
|
56
|
-
def exist?
|
57
|
-
super
|
58
|
-
rescue Error::Rugged => e
|
59
|
-
return false if e.net_status[:code] == :local_git_repository_does_not_exist
|
60
|
-
raise
|
13
|
+
def exclude_paths
|
14
|
+
dapp.local_git_artifact_exclude_paths
|
61
15
|
end
|
62
16
|
end
|
63
17
|
end
|
@@ -27,7 +27,7 @@ module Dapp
|
|
27
27
|
.reject { |job| ['0', 'false'].include? job.annotations["dapp/recreate"].to_s }
|
28
28
|
.select { |job| all_jobs_names.include? job.name }
|
29
29
|
.each do |job|
|
30
|
-
log_process("Delete
|
30
|
+
log_process("Delete hook job `#{job.name}` (dapp/recreate)", short: true) do
|
31
31
|
kube_delete_job!(job.name, all_pods_specs) unless dry_run?
|
32
32
|
end
|
33
33
|
end
|
@@ -133,13 +133,18 @@ module Dapp
|
|
133
133
|
watch_hooks_condition.signal
|
134
134
|
end
|
135
135
|
|
136
|
-
release.
|
136
|
+
cmd_res = release.helm_upgrade!
|
137
|
+
|
138
|
+
if cmd_res.error?
|
139
|
+
raise ::Dapp::Error::Command, code: :kube_helm_failed, data: {output: (cmd_res.stdout + cmd_res.stderr).strip}
|
140
|
+
else
|
141
|
+
watch_hooks_thr.join if !dry_run? && watch_hooks_thr && watch_hooks_thr.alive?
|
142
|
+
log_info((cmd_res.stdout + cmd_res.stderr).strip)
|
143
|
+
end
|
137
144
|
end
|
138
145
|
|
139
146
|
deployment_managers.each(&:after_deploy)
|
140
147
|
|
141
|
-
watch_hooks_thr.kill if !dry_run? && watch_hooks_thr && watch_hooks_thr.alive?
|
142
|
-
|
143
148
|
unless dry_run?
|
144
149
|
begin
|
145
150
|
::Timeout::timeout(self.options[:timeout] || 300) do
|
@@ -49,7 +49,7 @@ module Dapp
|
|
49
49
|
end.to_h
|
50
50
|
end
|
51
51
|
|
52
|
-
def
|
52
|
+
def helm_upgrade!
|
53
53
|
args = [
|
54
54
|
name, chart_path, additional_values_options,
|
55
55
|
set_options, upgrade_extra_options
|
@@ -57,7 +57,9 @@ module Dapp
|
|
57
57
|
|
58
58
|
dapp.kubernetes.create_namespace!(namespace) unless dapp.kubernetes.namespace?(namespace)
|
59
59
|
|
60
|
-
dapp.shellout
|
60
|
+
cmd = dapp.shellout "helm upgrade #{args.join(' ')}"
|
61
|
+
|
62
|
+
return cmd
|
61
63
|
end
|
62
64
|
|
63
65
|
def templates
|
@@ -2,6 +2,20 @@ module Dapp
|
|
2
2
|
module Kube
|
3
3
|
module Kubernetes::Client::Resource
|
4
4
|
class Pod < Base
|
5
|
+
# Returns:
|
6
|
+
# nil: no such condition yet
|
7
|
+
# "True" string: ready
|
8
|
+
# "False" string: not ready
|
9
|
+
def ready_condition_status
|
10
|
+
rd = self.ready_condition
|
11
|
+
return nil unless rd
|
12
|
+
return rd['status']
|
13
|
+
end
|
14
|
+
|
15
|
+
def ready_condition
|
16
|
+
status.fetch('conditions', {}).find {|condition| condition['type'] == 'Ready'}
|
17
|
+
end
|
18
|
+
|
5
19
|
def container_id(container_name)
|
6
20
|
container_status = spec.fetch('status', {})
|
7
21
|
.fetch('containerStatuses')
|
@@ -18,7 +18,7 @@ module Dapp
|
|
18
18
|
_, container_state_data = pod.container_state(name)
|
19
19
|
return if @processed_containers_ids.include? container_state_data['containerID']
|
20
20
|
|
21
|
-
pod_manager.
|
21
|
+
pod_manager.wait_till_launched!
|
22
22
|
|
23
23
|
pod = Kubernetes::Client::Resource::Pod.new(dapp.kubernetes.pod(pod_manager.name))
|
24
24
|
container_state, container_state_data = pod.container_state(name)
|
@@ -22,6 +22,8 @@ module Dapp
|
|
22
22
|
@deployment_before_deploy = Kubernetes::Client::Resource::Deployment.new(dapp.kubernetes.replace_deployment!(name, new_spec))
|
23
23
|
end
|
24
24
|
end
|
25
|
+
|
26
|
+
@deploy_began_at = Time.now
|
25
27
|
end
|
26
28
|
|
27
29
|
def after_deploy
|
@@ -116,7 +118,11 @@ module Dapp
|
|
116
118
|
known_log_timestamps_by_pod_and_container[pod.name][container_name] ||= Set.new
|
117
119
|
|
118
120
|
since_time = nil
|
119
|
-
|
121
|
+
# Если под еще не перешел в состоянии готовности, то можно вывести все логи которые имеются.
|
122
|
+
# Иначе выводим только новые логи с момента начала текущей сессии деплоя.
|
123
|
+
if [nil, "True"].include? pod.ready_condition_status
|
124
|
+
since_time = @deploy_began_at.utc.iso8601(9) if @deploy_began_at
|
125
|
+
end
|
120
126
|
|
121
127
|
log_lines_by_time = []
|
122
128
|
begin
|
@@ -147,34 +153,8 @@ module Dapp
|
|
147
153
|
end
|
148
154
|
end
|
149
155
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
if ready_condition['reason'] == 'ContainersNotReady'
|
154
|
-
Array(pod.status['containerStatuses']).each do |container_status|
|
155
|
-
next if container_status['ready']
|
156
|
-
|
157
|
-
waiting_reason = container_status.fetch('state', {}).fetch('waiting', {}).fetch('reason', nil)
|
158
|
-
case waiting_reason
|
159
|
-
when 'ImagePullBackOff', 'ErrImagePull'
|
160
|
-
raise Kubernetes::Error::Base,
|
161
|
-
code: :image_not_found,
|
162
|
-
data: {pod_name: pod.name,
|
163
|
-
reason: waiting_reason,
|
164
|
-
message: container_status['state']['waiting']['message']}
|
165
|
-
when 'CrashLoopBackOff'
|
166
|
-
raise Kubernetes::Error::Base,
|
167
|
-
code: :container_crash,
|
168
|
-
data: {pod_name: pod.name,
|
169
|
-
reason: waiting_reason,
|
170
|
-
message: container_status['state']['waiting']['message']}
|
171
|
-
end
|
172
|
-
end
|
173
|
-
else
|
174
|
-
dapp.with_log_indent do
|
175
|
-
dapp.log_warning("#{dapp.log_time}Unknown pod readiness condition reason '#{ready_condition['reason']}': #{ready_condition}", stream: dapp.service_stream)
|
176
|
-
end
|
177
|
-
end
|
156
|
+
pod_manager = Kubernetes::Manager::Pod.new(dapp, pod.name)
|
157
|
+
pod_manager.check_readiness_condition_if_available!(pod)
|
178
158
|
end # with_log_indent
|
179
159
|
end # rs_pods.each
|
180
160
|
end # with_log_indent
|
@@ -9,10 +9,44 @@ module Dapp
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
12
|
+
def check_readiness_condition_if_available!(pod)
|
13
|
+
return if [nil, "True"].include? pod.ready_condition_status
|
14
|
+
|
15
|
+
if pod.ready_condition['reason'] == 'ContainersNotReady'
|
16
|
+
[*Array(pod.status["initContainerStatuses"]), *Array(pod.status["containerStatuses"])].each do |container_status|
|
17
|
+
next if container_status['ready']
|
18
|
+
|
19
|
+
waiting_reason = container_status.fetch('state', {}).fetch('waiting', {}).fetch('reason', nil)
|
20
|
+
case waiting_reason
|
21
|
+
when 'ImagePullBackOff', 'ErrImagePull'
|
22
|
+
raise Kubernetes::Error::Default,
|
23
|
+
code: :bad_image,
|
24
|
+
data: {pod_name: pod.name,
|
25
|
+
reason: waiting_reason,
|
26
|
+
message: container_status['state']['waiting']['message']}
|
27
|
+
when 'CrashLoopBackOff'
|
28
|
+
raise Kubernetes::Error::Default,
|
29
|
+
code: :container_crash,
|
30
|
+
data: {pod_name: pod.name,
|
31
|
+
reason: waiting_reason,
|
32
|
+
message: container_status['state']['waiting']['message']}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
else
|
36
|
+
dapp.with_log_indent do
|
37
|
+
dapp.log_warning("#{dapp.log_time}Unknown pod readiness condition reason '#{pod.ready_condition['reason']}': #{pod.ready_condition}", stream: dapp.service_stream)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def wait_till_launched!
|
13
43
|
loop do
|
14
44
|
pod = Kubernetes::Client::Resource::Pod.new(dapp.kubernetes.pod(name))
|
15
|
-
|
45
|
+
|
46
|
+
break if pod.phase != "Pending"
|
47
|
+
|
48
|
+
check_readiness_condition_if_available!(pod)
|
49
|
+
|
16
50
|
sleep 0.1
|
17
51
|
end
|
18
52
|
end
|
data/lib/dapp/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dapp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.24.
|
4
|
+
version: 0.24.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dmitry Stolyarov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-01-
|
11
|
+
date: 2018-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mixlib-shellout
|
@@ -600,6 +600,7 @@ files:
|
|
600
600
|
- lib/dapp/dimg/dapp/command/tag.rb
|
601
601
|
- lib/dapp/dimg/dapp/dapp.rb
|
602
602
|
- lib/dapp/dimg/dapp/dappfile.rb
|
603
|
+
- lib/dapp/dimg/dapp/dimg.rb
|
603
604
|
- lib/dapp/dimg/dimg.rb
|
604
605
|
- lib/dapp/dimg/dimg/git_artifact.rb
|
605
606
|
- lib/dapp/dimg/dimg/path.rb
|
@@ -624,6 +625,7 @@ files:
|
|
624
625
|
- lib/dapp/dimg/filelock.rb
|
625
626
|
- lib/dapp/dimg/git_artifact.rb
|
626
627
|
- lib/dapp/dimg/git_repo/base.rb
|
628
|
+
- lib/dapp/dimg/git_repo/local.rb
|
627
629
|
- lib/dapp/dimg/git_repo/own.rb
|
628
630
|
- lib/dapp/dimg/git_repo/remote.rb
|
629
631
|
- lib/dapp/dimg/image/argument.rb
|