Class: GitJump::Database

Inherits:
Object
  • Object
show all
Defined in:
lib/git_jump/database.rb

Overview

Handles SQLite database operations for branch tracking

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(db_path) ⇒ Database

Returns a new instance of Database.



11
12
13
14
# File 'lib/git_jump/database.rb', line 11

def initialize(db_path)
  @db_path = db_path
  @db = nil
end

Instance Attribute Details

#db_pathObject (readonly)

Returns the value of attribute db_path.



9
10
11
# File 'lib/git_jump/database.rb', line 9

def db_path
  @db_path
end

Instance Method Details

#add_branch(project_id, branch_name) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/git_jump/database.rb', line 75

def add_branch(project_id, branch_name)
  now = Time.now.iso8601(3)

  # Try to insert, if already exists, update last_visited_at
  db.execute(
    <<-SQL,
      INSERT INTO branches (project_id, name, position, last_visited_at, created_at)
      VALUES (?, ?, 0, ?, ?)
      ON CONFLICT(project_id, name) DO UPDATE SET
        last_visited_at = ?,
        position = 0
    SQL
    [project_id, branch_name, now, now, now]
  )

  # Reorder positions based on last_visited_at
  reorder_branches(project_id)
end

#branch_at_index(project_id, index) ⇒ Object



117
118
119
120
121
122
# File 'lib/git_jump/database.rb', line 117

def branch_at_index(project_id, index)
  branches = list_branches(project_id)
  return nil if branches.empty? || index < 1 || index > branches.length

  branches[index - 1]["name"]
end

#cleanup_old_branches(project_id, max_count) ⇒ Object



144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/git_jump/database.rb', line 144

def cleanup_old_branches(project_id, max_count)
  branches = list_branches(project_id)
  return 0 if branches.length <= max_count

  to_delete = branches[max_count..]
  to_delete.each do |branch|
    db.execute("DELETE FROM branches WHERE id = ?", [branch["id"]])
  end

  reorder_branches(project_id)
  to_delete.length
end

#clear_branches(project_id, keep_patterns) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/git_jump/database.rb', line 124

def clear_branches(project_id, keep_patterns)
  return 0 if keep_patterns.empty?

  branches = list_branches(project_id)
  deleted = 0

  branches.each do |branch|
    branch_name = branch["name"]
    should_keep = keep_patterns.any? { |pattern| branch_name.match?(Regexp.new(pattern)) }

    unless should_keep
      db.execute("DELETE FROM branches WHERE id = ?", [branch["id"]])
      deleted += 1
    end
  end

  reorder_branches(project_id)
  deleted
end

#closeObject



171
172
173
# File 'lib/git_jump/database.rb', line 171

def close
  db&.close
end

#count_branches(project_id) ⇒ Object



157
158
159
160
161
162
# File 'lib/git_jump/database.rb', line 157

def count_branches(project_id)
  db.execute(
    "SELECT COUNT(*) as count FROM branches WHERE project_id = ?",
    [project_id]
  ).first["count"]
end

#dbObject

Lazy-load database connection



17
18
19
20
21
22
23
24
25
26
# File 'lib/git_jump/database.rb', line 17

def db
  @db ||= begin
    require "sqlite3" unless defined?(SQLite3)
    ensure_database_directory!
    connection = SQLite3::Database.new(db_path)
    connection.results_as_hash = true
    migrate!(connection)
    connection
  end
end

#find_or_create_project(path, basename) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/git_jump/database.rb', line 58

def find_or_create_project(path, basename)
  project = db.execute(
    "SELECT * FROM projects WHERE path = ?",
    [path]
  ).first

  return project if project

  now = Time.now.iso8601(3)
  db.execute(
    "INSERT INTO projects (path, basename, created_at, updated_at) VALUES (?, ?, ?, ?)",
    [path, basename, now, now]
  )

  db.execute("SELECT * FROM projects WHERE path = ?", [path]).first
end

#list_branches(project_id, limit: nil) ⇒ Object



94
95
96
97
98
99
100
# File 'lib/git_jump/database.rb', line 94

def list_branches(project_id, limit: nil)
  sql = "SELECT * FROM branches WHERE project_id = ? ORDER BY position ASC, last_visited_at DESC"
  sql += " LIMIT ?" if limit

  params = limit ? [project_id, limit] : [project_id]
  db.execute(sql, params)
end

#migrate!(connection) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/git_jump/database.rb', line 28

def migrate!(connection)
  connection.execute <<-SQL
    CREATE TABLE IF NOT EXISTS projects (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      path TEXT NOT NULL UNIQUE,
      basename TEXT NOT NULL,
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL
    );
  SQL

  connection.execute <<-SQL
    CREATE TABLE IF NOT EXISTS branches (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      project_id INTEGER NOT NULL,
      name TEXT NOT NULL,
      position INTEGER NOT NULL DEFAULT 0,
      last_visited_at TEXT NOT NULL,
      created_at TEXT NOT NULL,
      FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
      UNIQUE(project_id, name)
    );
  SQL

  connection.execute <<-SQL
    CREATE INDEX IF NOT EXISTS idx_branches_project_position#{" "}
      ON branches(project_id, position);
  SQL
end

#next_branch(project_id, current_branch) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/git_jump/database.rb', line 102

def next_branch(project_id, current_branch)
  branches = list_branches(project_id)
  return nil if branches.empty?

  current_index = branches.index { |b| b["name"] == current_branch }

  if current_index.nil?
    branches.first["name"]
  elsif current_index == branches.length - 1
    branches.first["name"]
  else
    branches[current_index + 1]["name"]
  end
end

#project_stats(project_id) ⇒ Object



164
165
166
167
168
169
# File 'lib/git_jump/database.rb', line 164

def project_stats(project_id)
  {
    total_branches: count_branches(project_id),
    most_recent: list_branches(project_id, limit: 1).first
  }
end