Class: Textus::Action::KeyMv

Inherits:
Base
  • Object
show all
Defined in:
lib/textus/action/key_mv.rb

Class Method Summary collapse

Methods inherited from Base

inherited, proposal_from

Methods included from Contract::DSL

#arg, #cli, #cli_stdin, #contract, #contract?, #summary, #surfaces, #verb, #view

Class Method Details

.apply_move(container:, call:, old_key:, new_key:, old_res:, new_res:) ⇒ Object



37
38
39
40
41
42
43
44
45
# File 'lib/textus/action/key_mv.rb', line 37

def self.apply_move(container:, call:, old_key:, new_key:, old_res:, new_res:)
  ensure_uid!(container: container, call: call, old_key: old_key, old_mentry: old_res.entry)
  container.compositor.move(
    from_key: old_key,
    to_key: new_key,
    new_mentry: new_res.entry,
    call: call,
  )
end

.call(container:, call:, old_key:, new_key:, dry_run: false) ⇒ Object



19
20
21
# File 'lib/textus/action/key_mv.rb', line 19

def self.call(container:, call:, old_key:, new_key:, dry_run: false)
  execute_move(container: container, call: call, old_key: old_key, new_key: new_key, dry_run: dry_run)
end

.dry_run_result(container:, old_key:, new_key:, old_res:, new_res:) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/textus/action/key_mv.rb', line 107

def self.dry_run_result(container:, old_key:, new_key:, old_res:, new_res:)
  pre_env = container.compositor.read(old_key)
  {
    "protocol" => Textus::PROTOCOL,
    "ok" => true,
    "dry_run" => true,
    "from_key" => old_key,
    "to_key" => new_key,
    "from_path" => old_res.path,
    "to_path" => new_res.path,
    "uid" => pre_env.uid,
  }
end

.ensure_uid!(container:, call:, old_key:, old_mentry:) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/textus/action/key_mv.rb', line 91

def self.ensure_uid!(container:, call:, old_key:, old_mentry:)
  pre_env = container.compositor.read(old_key)
  return if pre_env.uid

  container.compositor.write(
    old_key,
    mentry: old_mentry,
    payload: Textus::Store::Envelope::Writer::Payload.new(
      meta: pre_env.meta,
      body: pre_env.body,
      content: pre_env.content,
    ),
    call: call,
  )
end

.execute_move(container:, call:, old_key:, new_key:, dry_run:) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/textus/action/key_mv.rb', line 23

def self.execute_move(container:, call:, old_key:, new_key:, dry_run:)
  prepared = prepare(container: container, old_key: old_key, new_key: new_key)
  return prepared if prepared.is_a?(Dry::Monads::Result::Failure)

  old_res, new_res = prepared
  if dry_run
    return Success(dry_run_result(container: container, old_key: old_key, new_key: new_key, old_res: old_res,
                                  new_res: new_res))
  end

  envelope = apply_move(container: container, call: call, old_key: old_key, new_key: new_key, old_res: old_res, new_res: new_res)
  Success(success_result(old_key: old_key, new_key: new_key, old_res: old_res, new_res: new_res, envelope: envelope))
end

.prepare(container:, old_key:, new_key:) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/textus/action/key_mv.rb', line 60

def self.prepare(container:, old_key:, new_key:)
  Textus::Manifest::Data.validate_key!(old_key)
  Textus::Manifest::Data.validate_key!(new_key)
  return Failure(code: :usage_error, message: "mv: old and new keys are identical") if old_key == new_key

  old_res = container.manifest.resolver.resolve(old_key)
  new_res = container.manifest.resolver.resolve(new_key)
  return Failure(code: :not_found, message: "source key '#{old_key}' not found") unless container.compositor.exists?(old_key)

  zone_check = validate_zone_and_format(old_mentry: old_res.entry, new_mentry: new_res.entry)
  return zone_check if zone_check.is_a?(Dry::Monads::Result::Failure)

  if container.compositor.exists?(new_key)
    return Failure(code: :usage_error, message: "mv: target '#{new_key}' already exists at #{new_res.path}")
  end

  [old_res, new_res]
end

.success_result(old_key:, new_key:, old_res:, new_res:, envelope:) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/textus/action/key_mv.rb', line 47

def self.success_result(old_key:, new_key:, old_res:, new_res:, envelope:)
  {
    "protocol" => Textus::PROTOCOL,
    "ok" => true,
    "from_key" => old_key,
    "to_key" => new_key,
    "from_path" => old_res.path,
    "to_path" => new_res.path,
    "uid" => envelope.uid,
    "envelope" => envelope.to_h_for_wire,
  }
end

.validate_zone_and_format(old_mentry:, new_mentry:) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
# File 'lib/textus/action/key_mv.rb', line 79

def self.validate_zone_and_format(old_mentry:, new_mentry:)
  if old_mentry.lane != new_mentry.lane
    return Failure(code: :usage_error,
                   message: "mv: cross-zone move refused (#{old_mentry.lane} -> #{new_mentry.lane}). " \
                            "Use put+delete for cross-zone moves.")
  end
  return unless old_mentry.format != new_mentry.format

  Failure(code: :usage_error,
          message: "mv: format mismatch (#{old_mentry.format} -> #{new_mentry.format}); refusing.")
end