Class: Ace::Git::Worktree::Models::WorktreeMetadata

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/git/worktree/models/worktree_metadata.rb

Overview

Worktree metadata model for task frontmatter

Represents worktree information that gets added to task frontmatter to track the association between tasks and their worktrees.

Examples:

Create for a new worktree

 = WorktreeMetadata.new(
  branch: "081-fix-authentication-bug",
  path: ".ace-wt/task.081",
  created_at: Time.now
)

Load from task frontmatter

 = WorktreeMetadata.from_task_data(task_frontmatter_hash)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(branch:, path:, target_branch: nil, created_at: Time.now, updated_at: Time.now) ⇒ WorktreeMetadata

Initialize a new WorktreeMetadata

Parameters:

  • branch (String)

    Git branch name

  • path (String)

    Worktree path (relative to project root)

  • target_branch (String, nil) (defaults to: nil)

    PR target branch (default: nil for main)

  • created_at (Time) (defaults to: Time.now)

    When the worktree was created

  • updated_at (Time) (defaults to: Time.now)

    When the worktree was last updated



31
32
33
34
35
36
37
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 31

def initialize(branch:, path:, target_branch: nil, created_at: Time.now, updated_at: Time.now)
  @branch = branch.to_s
  @path = path.to_s
  @target_branch = target_branch&.to_s
  @created_at = created_at.is_a?(Time) ? created_at : Time.parse(created_at.to_s)
  @updated_at = updated_at.is_a?(Time) ? updated_at : Time.parse(updated_at.to_s)
end

Instance Attribute Details

#branchObject (readonly)

Returns the value of attribute branch.



22
23
24
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 22

def branch
  @branch
end

#created_atObject (readonly)

Returns the value of attribute created_at.



22
23
24
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 22

def created_at
  @created_at
end

#pathObject (readonly)

Returns the value of attribute path.



22
23
24
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 22

def path
  @path
end

#target_branchObject (readonly)

Returns the value of attribute target_branch.



22
23
24
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 22

def target_branch
  @target_branch
end

#updated_atObject (readonly)

Returns the value of attribute updated_at.



22
23
24
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 22

def updated_at
  @updated_at
end

Class Method Details

.find_by_branch(tasks, branch) ⇒ WorktreeMetadata?

Find worktree metadata by branch name

Examples:

 = WorktreeMetadata.find_by_branch(tasks, "081-fix-auth")

Parameters:

  • tasks (Array<Hash>)

    Array of task frontmatter hashes

  • branch (String)

    Branch name to search for

Returns:



215
216
217
218
219
220
221
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 215

def self.find_by_branch(tasks, branch)
  tasks.each do |task_data|
     = from_task_data(task_data)
    return  if  && .branch == branch
  end
  nil
end

.find_by_path(tasks, path) ⇒ WorktreeMetadata?

Find worktree metadata by path

Examples:

 = WorktreeMetadata.find_by_path(tasks, ".ace-wt/task.081")

Parameters:

  • tasks (Array<Hash>)

    Array of task frontmatter hashes

  • path (String)

    Path to search for

Returns:



231
232
233
234
235
236
237
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 231

def self.find_by_path(tasks, path)
  tasks.each do |task_data|
     = from_task_data(task_data)
    return  if  && .path == path
  end
  nil
end

.from_task_data(task_data) ⇒ WorktreeMetadata?

Load from task frontmatter hash

Examples:

 = WorktreeMetadata.from_task_data({
  "worktree" => {
    "branch" => "081-fix-auth",
    "path" => ".ace-wt/task.081",
    "target_branch" => "080-parent-branch",
    "created_at" => "2025-11-04 13:45:00"
  }
})

Parameters:

  • task_data (Hash)

    Task frontmatter data

Returns:



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 117

def self.from_task_data(task_data)
  worktree_data = task_data["worktree"]
  return nil unless worktree_data.is_a?(Hash)

  branch = worktree_data["branch"]
  path = worktree_data["path"]
  target_branch = worktree_data["target_branch"]
  return nil unless branch && path

  created_at = parse_time(worktree_data["created_at"]) || Time.now
  updated_at = parse_time(worktree_data["updated_at"]) || created_at

  new(
    branch: branch,
    path: path,
    target_branch: target_branch,
    created_at: created_at,
    updated_at: updated_at
  )
end

.from_worktree_info(worktree_info, project_root = Dir.pwd) ⇒ WorktreeMetadata

Create from a worktree info object

Examples:

 = WorktreeMetadata.from_worktree_info(worktree_info, "/project")

Parameters:

  • worktree_info (WorktreeInfo)

    Worktree information

  • project_root (String) (defaults to: Dir.pwd)

    Project root directory

Returns:



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 146

def self.from_worktree_info(worktree_info, project_root = Dir.pwd)
  require_relative "../atoms/path_expander"

  # Make path relative to project root
  relative_path = begin
    Atoms::PathExpander.relative_to_git_root(worktree_info.path, project_root)
  rescue
    worktree_info.path
  end

  new(
    branch: worktree_info.branch,
    path: relative_path,
    created_at: worktree_info.created_at || Time.now
  )
end

.merge_into_task_data(task_data, worktree_metadata) ⇒ Hash

Merge worktree metadata into task frontmatter

Examples:

updated_data = WorktreeMetadata.merge_into_task_data(
  existing_task_data,
  
)

Parameters:

  • task_data (Hash)

    Existing task frontmatter

  • worktree_metadata (WorktreeMetadata)

    Worktree metadata to merge

Returns:

  • (Hash)

    Updated task frontmatter



174
175
176
177
178
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 174

def self.merge_into_task_data(task_data, )
  updated_data = task_data.dup
  updated_data["worktree"] = .to_h
  updated_data
end

.parse_time(time_input) ⇒ Time?

Parse time from various formats

Parameters:

  • time_input (String, Time, nil)

    Time input

Returns:

  • (Time, nil)

    Parsed time or nil



278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 278

def self.parse_time(time_input)
  return nil if time_input.nil?

  case time_input
  when Time
    time_input
  when String
    Time.parse(time_input)
  end
rescue ArgumentError
  nil
end

.present_in_task?(task_data) ⇒ Boolean

Check if task has worktree metadata

Examples:

has_worktree = WorktreeMetadata.present_in_task?(task_data)

Parameters:

  • task_data (Hash)

    Task frontmatter

Returns:

  • (Boolean)

    true if worktree metadata is present



200
201
202
203
204
205
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 200

def self.present_in_task?(task_data)
  worktree_data = task_data["worktree"]
  worktree_data.is_a?(Hash) &&
    worktree_data["branch"] &&
    worktree_data["path"]
end

.remove_from_task_data(task_data) ⇒ Hash

Remove worktree metadata from task frontmatter

Examples:

clean_data = WorktreeMetadata.remove_from_task_data(task_data)

Parameters:

  • task_data (Hash)

    Task frontmatter

Returns:

  • (Hash)

    Task frontmatter without worktree metadata



187
188
189
190
191
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 187

def self.remove_from_task_data(task_data)
  updated_data = task_data.dup
  updated_data.delete("worktree")
  updated_data
end

Instance Method Details

#==(other) ⇒ Boolean Also known as: eql?

Equality comparison

Parameters:

Returns:

  • (Boolean)

    true if equal



243
244
245
246
247
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 243

def ==(other)
  return false unless other.is_a?(WorktreeMetadata)

  @branch == other.branch && @path == other.path
end

#age_daysFloat

Get the age of the worktree in days

Returns:

  • (Float)

    Age in days



71
72
73
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 71

def age_days
  (Time.now - @created_at) / (24 * 60 * 60)
end

#days_since_updateFloat

Get the time since last update in days

Returns:

  • (Float)

    Days since last update



78
79
80
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 78

def days_since_update
  (Time.now - @updated_at) / (24 * 60 * 60)
end

#hashInteger

Hash for using as hash keys

Returns:

  • (Integer)

    Hash value



254
255
256
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 254

def hash
  [@branch, @path].hash
end

#inspectString

Inspect representation

Returns:

  • (String)

    Detailed inspect string



268
269
270
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 268

def inspect
  "#<#{self.class.name} branch=#{@branch.inspect} path=#{@path.inspect} created=#{@created_at}>"
end

#recent?Boolean

Check if the worktree is recent (created within last 7 days)

Returns:

  • (Boolean)

    true if worktree is recent



57
58
59
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 57

def recent?
  @created_at > (Time.now - 7 * 24 * 60 * 60)
end

#stale?Boolean

Check if the worktree is stale (not updated in last 30 days)

Returns:

  • (Boolean)

    true if worktree is stale



64
65
66
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 64

def stale?
  @updated_at < (Time.now - 30 * 24 * 60 * 60)
end

#to_hHash

Convert to hash for YAML serialization

Returns:

  • (Hash)

    Hash representation



85
86
87
88
89
90
91
92
93
94
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 85

def to_h
  {
    "branch" => @branch,
    "path" => @path,
    "created_at" => @created_at.strftime("%Y-%m-%d %H:%M:%S"),
    "updated_at" => @updated_at.strftime("%Y-%m-%d %H:%M:%S")
  }.tap do |hash|
    hash["target_branch"] = @target_branch if @target_branch
  end
end

#to_sString

String representation

Returns:

  • (String)

    String representation



261
262
263
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 261

def to_s
  "#{@branch} at #{@path}"
end

#to_yamlString

Convert to YAML string

Returns:

  • (String)

    YAML representation



99
100
101
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 99

def to_yaml
  to_h.to_yaml
end

#update(branch: nil, path: nil) ⇒ WorktreeMetadata

Update the metadata with new information

Parameters:

  • branch (String, nil) (defaults to: nil)

    New branch name

  • path (String, nil) (defaults to: nil)

    New path

Returns:



44
45
46
47
48
49
50
51
52
# File 'lib/ace/git/worktree/models/worktree_metadata.rb', line 44

def update(branch: nil, path: nil)
  WorktreeMetadata.new(
    branch: branch || @branch,
    path: path || @path,
    target_branch: @target_branch,
    created_at: @created_at,
    updated_at: Time.now
  )
end