gdkbox 0.1.12 → 0.1.13

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b71b4f7e72836332b32feca0a6e3e0c485f8255fcfb0f1dc93c7792c3f6fc5ab
4
- data.tar.gz: 66e0331f211fd1df2b67694e42e65d8971502615b42c61093f86a3a465e06425
3
+ metadata.gz: 8df6faa5d2c2a7a0fe888195af92305774354b997ef5e0e2d1a7ee61469b60bf
4
+ data.tar.gz: 4c859a064721f68cdadc7a7140dc73b0d3a179a57fe3b538c63699c021115109
5
5
  SHA512:
6
- metadata.gz: b70d9d914b6ce31f0a644cae9260a98adb3540b0d76555a1ed4e72fc423b9602deb84b338b1b91cf29bf455546b248e875dbfa2e7fdc5dafc9b37322cb2d58be
7
- data.tar.gz: 73ebbfbfb11732b3d5fb9f40ea0d795a846c61ccb24d513c51684542424d2d78a7eef919e03d5d2007f64df3c3f0704cb75f07dbc3e7b494f90f9ae892daec43
6
+ metadata.gz: 9ebd61583a5e01145206ba5407e2fbaad1cf456bbfbb040ecc58e66d0d471c3a5566fca4d194467f9dcc988f5540f57f54c73edf96ac5805248a3c34996f4095
7
+ data.tar.gz: fd01809df5f90d1eff5229918f424c311577f15a756ea32328157ebdcaf237e5d1c998a1db87d004a07dbc77be413c4260cc17baaa9db58248f5087cd3488467
data/lib/gdkbox/box.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "shellwords"
3
4
  require "time"
4
5
 
5
6
  module GDKBox
@@ -209,22 +210,58 @@ module GDKBox
209
210
  url
210
211
  end
211
212
 
213
+ # The hydrate fetch, run inside the box. The filter is passed to `git
214
+ # fetch` directly and only persisted to config after the fetch succeeds
215
+ # (and, for a full hydrate, the previous filter is put back on failure),
216
+ # so an interrupted hydrate cannot leave the config claiming objects the
217
+ # store does not have (issue #8).
218
+ HYDRATE_SCRIPT = <<~'BASH'
219
+ set -e
220
+ if [ -n "$GDKBOX_HYDRATE_FILTER" ]; then
221
+ git fetch --refetch --progress --filter="$GDKBOX_HYDRATE_FILTER" origin
222
+ git config remote.origin.partialclonefilter "$GDKBOX_HYDRATE_FILTER"
223
+ else
224
+ prev=$(git config --get remote.origin.partialclonefilter || true)
225
+ git config --unset-all remote.origin.partialclonefilter || true
226
+ if ! git fetch --refetch --progress origin; then
227
+ if [ -n "$prev" ]; then git config remote.origin.partialclonefilter "$prev"; fi
228
+ echo "hydrate: fetch failed; previous filter config restored" >&2
229
+ exit 1
230
+ fi
231
+ git config --unset remote.origin.promisor || true
232
+ fi
233
+ BASH
234
+
212
235
  # Backfill the box's treeless GitLab clone so deep-history operations
213
236
  # (old rebases, blame, bisect) work. trees: true fetches only the missing
214
- # trees (much smaller; file contents stay lazy). Prepares the SSH client
215
- # first when origin is an SSH remote — a refetch without multiplexing
216
- # would hit the same throttling the lazy fetches do. Streams git's
217
- # progress lines to the block.
237
+ # trees (much smaller; file contents stay lazy).
238
+ #
239
+ # The fetch runs over SSH (`ssh -F <generated config> <alias>`), not
240
+ # `docker exec`: the remote is typically git@gitlab.com, and only an SSH
241
+ # session carries the user's forwarded agent — docker exec has no
242
+ # SSH_AUTH_SOCK, so it cannot authenticate at all (issue #8). The SSH
243
+ # client stanza (host key + multiplexing) is seeded first for SSH
244
+ # origins. Streams git's progress lines to the block; raises
245
+ # CommandError when the fetch fails.
218
246
  def hydrate!(trees: false, &progress)
219
- provisioner = Provisioner.new(docker: @docker, config: @config)
220
247
  origin = @docker.exec(
221
248
  container_name, "git remote get-url origin",
222
249
  user: @config.ssh_user, workdir: @config.gitlab_checkout_path
223
250
  ).stdout.strip
224
251
  if (host = self.class.remote_ssh_host(origin))
225
- provisioner.setup_git_ssh(container_name, host)
252
+ Provisioner.new(docker: @docker, config: @config)
253
+ .setup_git_ssh(container_name, host)
226
254
  end
227
- provisioner.hydrate(container_name, trees: trees, &progress)
255
+
256
+ filter = trees ? "blob:none" : ""
257
+ remote_cmd = "cd #{Shellwords.escape(@config.gitlab_checkout_path)} && " \
258
+ "GDKBOX_HYDRATE_FILTER=#{Shellwords.escape(filter)} " \
259
+ "bash -c #{Shellwords.escape(HYDRATE_SCRIPT)}"
260
+ argv = ["ssh", "-F", @config.ssh_config_path, ssh_host_alias, remote_cmd]
261
+ result = @shell.stream_tty(*argv, &progress)
262
+ raise CommandError.new(argv, result.status, "") unless result.success?
263
+
264
+ result
228
265
  end
229
266
 
230
267
  # Seed a git identity into the box so `git commit` works there. Falls back
data/lib/gdkbox/docker.rb CHANGED
@@ -223,21 +223,6 @@ module GDKBox
223
223
  check ? @shell.run!(*cmd, input: input) : @shell.run(*cmd, input: input)
224
224
  end
225
225
 
226
- # Like #exec, but for long-running scripts whose output should be seen
227
- # live (e.g. a multi-GB git fetch): runs under a PTY and yields each
228
- # output line as it appears. Raises CommandError on a non-zero exit.
229
- def exec_stream(name, script, user: nil, workdir: nil, env: {}, &block)
230
- cmd = ["docker", "exec"]
231
- cmd.push("-u", user) if user
232
- cmd.push("-w", workdir) if workdir
233
- env.each { |key, value| cmd.push("-e", "#{key}=#{value}") }
234
- cmd.push(name, "bash", "-lc", script)
235
- result = @shell.stream_tty(*cmd, &block)
236
- raise CommandError.new(cmd, result.status, "") unless result.success?
237
-
238
- result
239
- end
240
-
241
226
  # Copy a host path into a container at dest (a full destination path).
242
227
  def cp_into(name, src, dest)
243
228
  @shell.run!("docker", "cp", src, "#{name}:#{dest}")
@@ -183,27 +183,6 @@ module GDKBox
183
183
  git fetch --quiet origin
184
184
  BASH
185
185
 
186
- # Backfills the treeless GitLab clone (the image clones with
187
- # --filter=tree:0, so operations spanning a large history gap storm the
188
- # network with lazy fetches and fail; see #7). Two levels:
189
- #
190
- # - GDKBOX_HYDRATE_FILTER=blob:none — fetch all missing trees, keep file
191
- # contents lazy. A fraction of the download; enough for deep rebases,
192
- # which mostly storm tree fetches.
193
- # - no filter (full) — fetch everything and drop the promisor config;
194
- # the repository behaves like a normal full clone afterwards.
195
- HYDRATE = <<~'BASH'
196
- set -e
197
- if [ -n "$GDKBOX_HYDRATE_FILTER" ]; then
198
- git config remote.origin.partialclonefilter "$GDKBOX_HYDRATE_FILTER"
199
- git fetch --refetch --progress origin
200
- else
201
- git config --unset-all remote.origin.partialclonefilter || true
202
- git fetch --refetch --progress origin
203
- git config --unset remote.origin.promisor || true
204
- fi
205
- BASH
206
-
207
186
  def initialize(docker:, config:)
208
187
  @docker = docker
209
188
  @config = config
@@ -252,18 +231,6 @@ module GDKBox
252
231
  )
253
232
  end
254
233
 
255
- # Hydrate the GitLab checkout, streaming git's progress lines to the
256
- # block. trees: true fetches trees only (blobs stay lazy).
257
- def hydrate(container_name, trees: false, &block)
258
- @docker.exec_stream(
259
- container_name, HYDRATE,
260
- user: @config.ssh_user,
261
- workdir: @config.gitlab_checkout_path,
262
- env: { "GDKBOX_HYDRATE_FILTER" => (trees ? "blob:none" : "") },
263
- &block
264
- )
265
- end
266
-
267
234
  def setup_git_ssh(container_name, host)
268
235
  @docker.exec(
269
236
  container_name, GIT_SSH_SETUP,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GDKBox
4
- VERSION = "0.1.12"
4
+ VERSION = "0.1.13"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gdkbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.12
4
+ version: 0.1.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - jotolo