git-pkgs 0.2.0 → 0.3.0
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/CHANGELOG.md +15 -1
- data/README.md +60 -2
- data/lib/git/pkgs/cli.rb +8 -3
- data/lib/git/pkgs/color.rb +82 -0
- data/lib/git/pkgs/commands/blame.rb +23 -20
- data/lib/git/pkgs/commands/branch.rb +11 -35
- data/lib/git/pkgs/commands/diff.rb +27 -35
- data/lib/git/pkgs/commands/history.rb +14 -16
- data/lib/git/pkgs/commands/hooks.rb +2 -0
- data/lib/git/pkgs/commands/info.rb +3 -5
- data/lib/git/pkgs/commands/init.rb +4 -5
- data/lib/git/pkgs/commands/list.rb +21 -18
- data/lib/git/pkgs/commands/log.rb +157 -0
- data/lib/git/pkgs/commands/schema.rb +161 -0
- data/lib/git/pkgs/commands/search.rb +10 -11
- data/lib/git/pkgs/commands/show.rb +17 -23
- data/lib/git/pkgs/commands/{outdated.rb → stale.rb} +16 -13
- data/lib/git/pkgs/commands/stats.rb +59 -17
- data/lib/git/pkgs/commands/tree.rb +13 -10
- data/lib/git/pkgs/commands/update.rb +55 -58
- data/lib/git/pkgs/commands/upgrade.rb +54 -0
- data/lib/git/pkgs/commands/why.rb +5 -10
- data/lib/git/pkgs/database.rb +55 -1
- data/lib/git/pkgs/output.rb +44 -0
- data/lib/git/pkgs/pager.rb +68 -0
- data/lib/git/pkgs/repository.rb +3 -3
- data/lib/git/pkgs/version.rb +1 -1
- data/lib/git/pkgs.rb +6 -1
- metadata +8 -2
|
@@ -4,6 +4,8 @@ module Git
|
|
|
4
4
|
module Pkgs
|
|
5
5
|
module Commands
|
|
6
6
|
class Info
|
|
7
|
+
include Output
|
|
8
|
+
|
|
7
9
|
def initialize(args)
|
|
8
10
|
@args = args
|
|
9
11
|
@options = parse_options
|
|
@@ -11,11 +13,7 @@ module Git
|
|
|
11
13
|
|
|
12
14
|
def run
|
|
13
15
|
repo = Repository.new
|
|
14
|
-
|
|
15
|
-
unless Database.exists?(repo.git_dir)
|
|
16
|
-
$stderr.puts "Database not initialized. Run 'git pkgs init' first."
|
|
17
|
-
exit 1
|
|
18
|
-
end
|
|
16
|
+
require_database(repo)
|
|
19
17
|
|
|
20
18
|
db_path = Database.path(repo.git_dir)
|
|
21
19
|
Database.connect(repo.git_dir)
|
|
@@ -4,6 +4,8 @@ module Git
|
|
|
4
4
|
module Pkgs
|
|
5
5
|
module Commands
|
|
6
6
|
class Init
|
|
7
|
+
include Output
|
|
8
|
+
|
|
7
9
|
BATCH_SIZE = 100
|
|
8
10
|
SNAPSHOT_INTERVAL = 20 # Store snapshot every N dependency-changing commits
|
|
9
11
|
|
|
@@ -21,15 +23,12 @@ module Git
|
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
Database.drop if @options[:force]
|
|
24
|
-
Database.connect(repo.git_dir)
|
|
26
|
+
Database.connect(repo.git_dir, check_version: false)
|
|
25
27
|
Database.create_schema(with_indexes: false)
|
|
26
28
|
Database.optimize_for_bulk_writes
|
|
27
29
|
|
|
28
30
|
branch_name = @options[:branch] || repo.default_branch
|
|
29
|
-
unless repo.branch_exists?(branch_name)
|
|
30
|
-
$stderr.puts "Branch '#{branch_name}' not found"
|
|
31
|
-
exit 1
|
|
32
|
-
end
|
|
31
|
+
error "Branch '#{branch_name}' not found" unless repo.branch_exists?(branch_name)
|
|
33
32
|
|
|
34
33
|
branch = Models::Branch.find_or_create(branch_name)
|
|
35
34
|
analyzer = Analyzer.new(repo)
|
|
@@ -4,6 +4,8 @@ module Git
|
|
|
4
4
|
module Pkgs
|
|
5
5
|
module Commands
|
|
6
6
|
class List
|
|
7
|
+
include Output
|
|
8
|
+
|
|
7
9
|
def initialize(args)
|
|
8
10
|
@args = args
|
|
9
11
|
@options = parse_options
|
|
@@ -11,26 +13,19 @@ module Git
|
|
|
11
13
|
|
|
12
14
|
def run
|
|
13
15
|
repo = Repository.new
|
|
14
|
-
|
|
15
|
-
unless Database.exists?(repo.git_dir)
|
|
16
|
-
$stderr.puts "Database not initialized. Run 'git pkgs init' first."
|
|
17
|
-
exit 1
|
|
18
|
-
end
|
|
16
|
+
require_database(repo)
|
|
19
17
|
|
|
20
18
|
Database.connect(repo.git_dir)
|
|
21
19
|
|
|
22
20
|
commit_sha = @options[:commit] || repo.head_sha
|
|
23
21
|
target_commit = Models::Commit.find_by(sha: commit_sha)
|
|
24
22
|
|
|
25
|
-
unless target_commit
|
|
26
|
-
$stderr.puts "Commit #{commit_sha[0, 7]} not found in database"
|
|
27
|
-
exit 1
|
|
28
|
-
end
|
|
23
|
+
error "Commit #{commit_sha[0, 7]} not found in database" unless target_commit
|
|
29
24
|
|
|
30
25
|
deps = compute_dependencies_at_commit(target_commit, repo)
|
|
31
26
|
|
|
32
27
|
if deps.empty?
|
|
33
|
-
|
|
28
|
+
empty_result "No dependencies found"
|
|
34
29
|
return
|
|
35
30
|
end
|
|
36
31
|
|
|
@@ -47,16 +42,20 @@ module Git
|
|
|
47
42
|
require "json"
|
|
48
43
|
puts JSON.pretty_generate(deps)
|
|
49
44
|
else
|
|
50
|
-
|
|
45
|
+
paginate { output_text(deps) }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
51
48
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
49
|
+
def output_text(deps)
|
|
50
|
+
grouped = deps.group_by { |d| [d[:manifest_path], d[:ecosystem]] }
|
|
51
|
+
|
|
52
|
+
grouped.each do |(path, platform), manifest_deps|
|
|
53
|
+
puts "#{path} (#{platform}):"
|
|
54
|
+
manifest_deps.sort_by { |d| d[:name] }.each do |dep|
|
|
55
|
+
type_suffix = dep[:dependency_type] ? " [#{dep[:dependency_type]}]" : ""
|
|
56
|
+
puts " #{dep[:name]} #{dep[:requirement]}#{type_suffix}"
|
|
59
57
|
end
|
|
58
|
+
puts
|
|
60
59
|
end
|
|
61
60
|
end
|
|
62
61
|
|
|
@@ -144,6 +143,10 @@ module Git
|
|
|
144
143
|
options[:format] = v
|
|
145
144
|
end
|
|
146
145
|
|
|
146
|
+
opts.on("--no-pager", "Do not pipe output into a pager") do
|
|
147
|
+
options[:no_pager] = true
|
|
148
|
+
end
|
|
149
|
+
|
|
147
150
|
opts.on("-h", "--help", "Show this help") do
|
|
148
151
|
puts opts
|
|
149
152
|
exit
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "time"
|
|
4
|
+
|
|
5
|
+
module Git
|
|
6
|
+
module Pkgs
|
|
7
|
+
module Commands
|
|
8
|
+
class Log
|
|
9
|
+
include Output
|
|
10
|
+
|
|
11
|
+
def initialize(args)
|
|
12
|
+
@args = args
|
|
13
|
+
@options = parse_options
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def run
|
|
17
|
+
repo = Repository.new
|
|
18
|
+
require_database(repo)
|
|
19
|
+
|
|
20
|
+
Database.connect(repo.git_dir)
|
|
21
|
+
|
|
22
|
+
commits = Models::Commit
|
|
23
|
+
.where(has_dependency_changes: true)
|
|
24
|
+
.order(committed_at: :desc)
|
|
25
|
+
|
|
26
|
+
commits = commits.where("author_name LIKE ? OR author_email LIKE ?",
|
|
27
|
+
"%#{@options[:author]}%", "%#{@options[:author]}%") if @options[:author]
|
|
28
|
+
commits = commits.where("committed_at >= ?", parse_time(@options[:since])) if @options[:since]
|
|
29
|
+
commits = commits.where("committed_at <= ?", parse_time(@options[:until])) if @options[:until]
|
|
30
|
+
|
|
31
|
+
commits = commits.limit(@options[:limit] || 20)
|
|
32
|
+
|
|
33
|
+
if commits.empty?
|
|
34
|
+
empty_result "No commits with dependency changes found"
|
|
35
|
+
return
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
if @options[:format] == "json"
|
|
39
|
+
output_json(commits)
|
|
40
|
+
else
|
|
41
|
+
paginate { output_text(commits) }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def output_text(commits)
|
|
46
|
+
commits.each do |commit|
|
|
47
|
+
changes = commit.dependency_changes
|
|
48
|
+
changes = changes.where(ecosystem: @options[:ecosystem]) if @options[:ecosystem]
|
|
49
|
+
next if changes.empty?
|
|
50
|
+
|
|
51
|
+
puts "#{commit.short_sha} #{commit.message&.lines&.first&.strip}"
|
|
52
|
+
puts "Author: #{commit.author_name} <#{commit.author_email}>"
|
|
53
|
+
puts "Date: #{commit.committed_at.strftime("%Y-%m-%d")}"
|
|
54
|
+
puts
|
|
55
|
+
|
|
56
|
+
added = changes.select { |c| c.change_type == "added" }
|
|
57
|
+
modified = changes.select { |c| c.change_type == "modified" }
|
|
58
|
+
removed = changes.select { |c| c.change_type == "removed" }
|
|
59
|
+
|
|
60
|
+
added.each do |change|
|
|
61
|
+
puts " + #{change.name} #{change.requirement}"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
modified.each do |change|
|
|
65
|
+
puts " ~ #{change.name} #{change.previous_requirement} -> #{change.requirement}"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
removed.each do |change|
|
|
69
|
+
puts " - #{change.name}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
puts
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def output_json(commits)
|
|
77
|
+
require "json"
|
|
78
|
+
|
|
79
|
+
data = commits.map do |commit|
|
|
80
|
+
changes = commit.dependency_changes
|
|
81
|
+
changes = changes.where(ecosystem: @options[:ecosystem]) if @options[:ecosystem]
|
|
82
|
+
|
|
83
|
+
{
|
|
84
|
+
sha: commit.sha,
|
|
85
|
+
short_sha: commit.short_sha,
|
|
86
|
+
message: commit.message&.lines&.first&.strip,
|
|
87
|
+
author_name: commit.author_name,
|
|
88
|
+
author_email: commit.author_email,
|
|
89
|
+
date: commit.committed_at.iso8601,
|
|
90
|
+
changes: changes.map do |change|
|
|
91
|
+
{
|
|
92
|
+
name: change.name,
|
|
93
|
+
change_type: change.change_type,
|
|
94
|
+
requirement: change.requirement,
|
|
95
|
+
previous_requirement: change.previous_requirement,
|
|
96
|
+
ecosystem: change.ecosystem
|
|
97
|
+
}
|
|
98
|
+
end
|
|
99
|
+
}
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
puts JSON.pretty_generate(data)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def parse_time(str)
|
|
106
|
+
Time.parse(str)
|
|
107
|
+
rescue ArgumentError
|
|
108
|
+
error "Invalid date format: #{str}"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def parse_options
|
|
112
|
+
options = {}
|
|
113
|
+
|
|
114
|
+
parser = OptionParser.new do |opts|
|
|
115
|
+
opts.banner = "Usage: git pkgs log [options]"
|
|
116
|
+
|
|
117
|
+
opts.on("-e", "--ecosystem=NAME", "Filter by ecosystem") do |v|
|
|
118
|
+
options[:ecosystem] = v
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
opts.on("--author=NAME", "Filter by author name or email") do |v|
|
|
122
|
+
options[:author] = v
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
opts.on("--since=DATE", "Show commits after date") do |v|
|
|
126
|
+
options[:since] = v
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
opts.on("--until=DATE", "Show commits before date") do |v|
|
|
130
|
+
options[:until] = v
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
opts.on("-n", "--limit=N", Integer, "Limit commits (default: 20)") do |v|
|
|
134
|
+
options[:limit] = v
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
opts.on("-f", "--format=FORMAT", "Output format (text, json)") do |v|
|
|
138
|
+
options[:format] = v
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
opts.on("--no-pager", "Do not pipe output into a pager") do
|
|
142
|
+
options[:no_pager] = true
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
opts.on("-h", "--help", "Show this help") do
|
|
146
|
+
puts opts
|
|
147
|
+
exit
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
parser.parse!(@args)
|
|
152
|
+
options
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Git
|
|
4
|
+
module Pkgs
|
|
5
|
+
module Commands
|
|
6
|
+
class Schema
|
|
7
|
+
include Output
|
|
8
|
+
|
|
9
|
+
FORMATS = %w[text sql json markdown].freeze
|
|
10
|
+
|
|
11
|
+
def initialize(args)
|
|
12
|
+
@args = args
|
|
13
|
+
@options = parse_options
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def run
|
|
17
|
+
repo = Repository.new
|
|
18
|
+
require_database(repo)
|
|
19
|
+
|
|
20
|
+
Database.connect(repo.git_dir)
|
|
21
|
+
tables = fetch_schema
|
|
22
|
+
|
|
23
|
+
case @options[:format]
|
|
24
|
+
when "sql"
|
|
25
|
+
output_sql(tables)
|
|
26
|
+
when "json"
|
|
27
|
+
output_json(tables)
|
|
28
|
+
when "markdown"
|
|
29
|
+
output_markdown(tables)
|
|
30
|
+
else
|
|
31
|
+
output_text(tables)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def fetch_schema
|
|
36
|
+
conn = ActiveRecord::Base.connection
|
|
37
|
+
tables = {}
|
|
38
|
+
|
|
39
|
+
conn.tables.sort.each do |table_name|
|
|
40
|
+
next if table_name == "ar_internal_metadata"
|
|
41
|
+
next if table_name == "schema_migrations"
|
|
42
|
+
|
|
43
|
+
columns = conn.columns(table_name).map do |col|
|
|
44
|
+
{
|
|
45
|
+
name: col.name,
|
|
46
|
+
type: col.type,
|
|
47
|
+
sql_type: col.sql_type,
|
|
48
|
+
null: col.null,
|
|
49
|
+
default: col.default
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
indexes = conn.indexes(table_name).map do |idx|
|
|
54
|
+
{
|
|
55
|
+
name: idx.name,
|
|
56
|
+
columns: idx.columns,
|
|
57
|
+
unique: idx.unique
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
tables[table_name] = { columns: columns, indexes: indexes }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
tables
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def output_text(tables)
|
|
68
|
+
tables.each do |table_name, info|
|
|
69
|
+
puts "#{table_name}"
|
|
70
|
+
puts "-" * table_name.length
|
|
71
|
+
|
|
72
|
+
info[:columns].each do |col|
|
|
73
|
+
nullable = col[:null] ? "NULL" : "NOT NULL"
|
|
74
|
+
default = col[:default] ? " DEFAULT #{col[:default]}" : ""
|
|
75
|
+
puts " #{col[:name].ljust(25)} #{col[:sql_type].ljust(15)} #{nullable}#{default}"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
if info[:indexes].any?
|
|
79
|
+
puts
|
|
80
|
+
puts " Indexes:"
|
|
81
|
+
info[:indexes].each do |idx|
|
|
82
|
+
unique = idx[:unique] ? "UNIQUE " : ""
|
|
83
|
+
puts " #{unique}#{idx[:name]} (#{idx[:columns].join(', ')})"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
puts
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def output_sql(tables)
|
|
92
|
+
conn = ActiveRecord::Base.connection
|
|
93
|
+
|
|
94
|
+
tables.each do |table_name, info|
|
|
95
|
+
sql = conn.execute("SELECT sql FROM sqlite_master WHERE type='table' AND name='#{table_name}'").first
|
|
96
|
+
puts sql["sql"] + ";" if sql
|
|
97
|
+
puts
|
|
98
|
+
|
|
99
|
+
info[:indexes].each do |idx|
|
|
100
|
+
idx_sql = conn.execute("SELECT sql FROM sqlite_master WHERE type='index' AND name='#{idx[:name]}'").first
|
|
101
|
+
puts idx_sql["sql"] + ";" if idx_sql && idx_sql["sql"]
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
puts if info[:indexes].any?
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def output_json(tables)
|
|
109
|
+
require "json"
|
|
110
|
+
puts JSON.pretty_generate(tables)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def output_markdown(tables)
|
|
114
|
+
tables.each do |table_name, info|
|
|
115
|
+
puts "## #{table_name}"
|
|
116
|
+
puts
|
|
117
|
+
puts "| Column | Type | Nullable | Default |"
|
|
118
|
+
puts "|--------|------|----------|---------|"
|
|
119
|
+
|
|
120
|
+
info[:columns].each do |col|
|
|
121
|
+
nullable = col[:null] ? "Yes" : "No"
|
|
122
|
+
default = col[:default] || ""
|
|
123
|
+
puts "| #{col[:name]} | #{col[:sql_type]} | #{nullable} | #{default} |"
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
if info[:indexes].any?
|
|
127
|
+
puts
|
|
128
|
+
puts "**Indexes:**"
|
|
129
|
+
info[:indexes].each do |idx|
|
|
130
|
+
unique = idx[:unique] ? " (unique)" : ""
|
|
131
|
+
puts "- `#{idx[:name]}`#{unique}: #{idx[:columns].join(', ')}"
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
puts
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def parse_options
|
|
140
|
+
options = { format: "text" }
|
|
141
|
+
|
|
142
|
+
parser = OptionParser.new do |opts|
|
|
143
|
+
opts.banner = "Usage: git pkgs schema [options]"
|
|
144
|
+
|
|
145
|
+
opts.on("--format=FORMAT", FORMATS, "Output format: #{FORMATS.join(', ')} (default: text)") do |v|
|
|
146
|
+
options[:format] = v
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
opts.on("-h", "--help", "Show this help") do
|
|
150
|
+
puts opts
|
|
151
|
+
exit
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
parser.parse!(@args)
|
|
156
|
+
options
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
@@ -4,6 +4,8 @@ module Git
|
|
|
4
4
|
module Pkgs
|
|
5
5
|
module Commands
|
|
6
6
|
class Search
|
|
7
|
+
include Output
|
|
8
|
+
|
|
7
9
|
def initialize(args)
|
|
8
10
|
@args = args
|
|
9
11
|
@options = parse_options
|
|
@@ -12,17 +14,10 @@ module Git
|
|
|
12
14
|
def run
|
|
13
15
|
pattern = @args.first
|
|
14
16
|
|
|
15
|
-
unless pattern
|
|
16
|
-
$stderr.puts "Usage: git pkgs search <pattern>"
|
|
17
|
-
exit 1
|
|
18
|
-
end
|
|
17
|
+
error "Usage: git pkgs search <pattern>" unless pattern
|
|
19
18
|
|
|
20
19
|
repo = Repository.new
|
|
21
|
-
|
|
22
|
-
unless Database.exists?(repo.git_dir)
|
|
23
|
-
$stderr.puts "Database not initialized. Run 'git pkgs init' first."
|
|
24
|
-
exit 1
|
|
25
|
-
end
|
|
20
|
+
require_database(repo)
|
|
26
21
|
|
|
27
22
|
Database.connect(repo.git_dir)
|
|
28
23
|
|
|
@@ -43,14 +38,14 @@ module Git
|
|
|
43
38
|
matches = query.distinct.pluck(:name, :ecosystem)
|
|
44
39
|
|
|
45
40
|
if matches.empty?
|
|
46
|
-
|
|
41
|
+
empty_result "No dependencies found matching '#{pattern}'"
|
|
47
42
|
return
|
|
48
43
|
end
|
|
49
44
|
|
|
50
45
|
if @options[:format] == "json"
|
|
51
46
|
output_json(matches, pattern)
|
|
52
47
|
else
|
|
53
|
-
output_text(matches, pattern)
|
|
48
|
+
paginate { output_text(matches, pattern) }
|
|
54
49
|
end
|
|
55
50
|
end
|
|
56
51
|
|
|
@@ -137,6 +132,10 @@ module Git
|
|
|
137
132
|
options[:format] = v
|
|
138
133
|
end
|
|
139
134
|
|
|
135
|
+
opts.on("--no-pager", "Do not pipe output into a pager") do
|
|
136
|
+
options[:no_pager] = true
|
|
137
|
+
end
|
|
138
|
+
|
|
140
139
|
opts.on("-h", "--help", "Show this help") do
|
|
141
140
|
puts opts
|
|
142
141
|
exit
|
|
@@ -4,6 +4,8 @@ module Git
|
|
|
4
4
|
module Pkgs
|
|
5
5
|
module Commands
|
|
6
6
|
class Show
|
|
7
|
+
include Output
|
|
8
|
+
|
|
7
9
|
def initialize(args)
|
|
8
10
|
@args = args
|
|
9
11
|
@options = parse_options
|
|
@@ -13,27 +15,15 @@ module Git
|
|
|
13
15
|
ref = @args.shift || "HEAD"
|
|
14
16
|
|
|
15
17
|
repo = Repository.new
|
|
16
|
-
|
|
17
|
-
unless Database.exists?(repo.git_dir)
|
|
18
|
-
$stderr.puts "Database not initialized. Run 'git pkgs init' first."
|
|
19
|
-
exit 1
|
|
20
|
-
end
|
|
18
|
+
require_database(repo)
|
|
21
19
|
|
|
22
20
|
Database.connect(repo.git_dir)
|
|
23
21
|
|
|
24
22
|
sha = repo.rev_parse(ref)
|
|
25
|
-
|
|
26
|
-
unless sha
|
|
27
|
-
$stderr.puts "Could not resolve '#{ref}'"
|
|
28
|
-
exit 1
|
|
29
|
-
end
|
|
23
|
+
error "Could not resolve '#{ref}'" unless sha
|
|
30
24
|
|
|
31
25
|
commit = find_or_create_commit(repo, sha)
|
|
32
|
-
|
|
33
|
-
unless commit
|
|
34
|
-
$stderr.puts "Commit '#{sha[0..7]}' not found"
|
|
35
|
-
exit 1
|
|
36
|
-
end
|
|
26
|
+
error "Commit '#{sha[0..7]}' not found" unless commit
|
|
37
27
|
|
|
38
28
|
changes = Models::DependencyChange
|
|
39
29
|
.includes(:commit, :manifest)
|
|
@@ -44,14 +34,14 @@ module Git
|
|
|
44
34
|
end
|
|
45
35
|
|
|
46
36
|
if changes.empty?
|
|
47
|
-
|
|
37
|
+
empty_result "No dependency changes in #{commit.short_sha}"
|
|
48
38
|
return
|
|
49
39
|
end
|
|
50
40
|
|
|
51
41
|
if @options[:format] == "json"
|
|
52
42
|
output_json(commit, changes)
|
|
53
43
|
else
|
|
54
|
-
output_text(commit, changes)
|
|
44
|
+
paginate { output_text(commit, changes) }
|
|
55
45
|
end
|
|
56
46
|
end
|
|
57
47
|
|
|
@@ -66,25 +56,25 @@ module Git
|
|
|
66
56
|
removed = changes.select { |c| c.change_type == "removed" }
|
|
67
57
|
|
|
68
58
|
if added.any?
|
|
69
|
-
puts "Added:"
|
|
59
|
+
puts Color.green("Added:")
|
|
70
60
|
added.each do |change|
|
|
71
|
-
puts " #{change.name} #{change.requirement} (#{change.ecosystem}, #{change.manifest.path})"
|
|
61
|
+
puts Color.green(" + #{change.name} #{change.requirement} (#{change.ecosystem}, #{change.manifest.path})")
|
|
72
62
|
end
|
|
73
63
|
puts
|
|
74
64
|
end
|
|
75
65
|
|
|
76
66
|
if modified.any?
|
|
77
|
-
puts "Modified:"
|
|
67
|
+
puts Color.yellow("Modified:")
|
|
78
68
|
modified.each do |change|
|
|
79
|
-
puts " #{change.name} #{change.previous_requirement} -> #{change.requirement} (#{change.ecosystem}, #{change.manifest.path})"
|
|
69
|
+
puts Color.yellow(" ~ #{change.name} #{change.previous_requirement} -> #{change.requirement} (#{change.ecosystem}, #{change.manifest.path})")
|
|
80
70
|
end
|
|
81
71
|
puts
|
|
82
72
|
end
|
|
83
73
|
|
|
84
74
|
if removed.any?
|
|
85
|
-
puts "Removed:"
|
|
75
|
+
puts Color.red("Removed:")
|
|
86
76
|
removed.each do |change|
|
|
87
|
-
puts " #{change.name} #{change.requirement} (#{change.ecosystem}, #{change.manifest.path})"
|
|
77
|
+
puts Color.red(" - #{change.name} #{change.requirement} (#{change.ecosystem}, #{change.manifest.path})")
|
|
88
78
|
end
|
|
89
79
|
puts
|
|
90
80
|
end
|
|
@@ -151,6 +141,10 @@ module Git
|
|
|
151
141
|
options[:format] = v
|
|
152
142
|
end
|
|
153
143
|
|
|
144
|
+
opts.on("--no-pager", "Do not pipe output into a pager") do
|
|
145
|
+
options[:no_pager] = true
|
|
146
|
+
end
|
|
147
|
+
|
|
154
148
|
opts.on("-h", "--help", "Show this help") do
|
|
155
149
|
puts opts
|
|
156
150
|
exit
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
module Git
|
|
4
4
|
module Pkgs
|
|
5
5
|
module Commands
|
|
6
|
-
class
|
|
6
|
+
class Stale
|
|
7
|
+
include Output
|
|
8
|
+
|
|
7
9
|
def initialize(args)
|
|
8
10
|
@args = args
|
|
9
11
|
@options = parse_options
|
|
@@ -11,21 +13,14 @@ module Git
|
|
|
11
13
|
|
|
12
14
|
def run
|
|
13
15
|
repo = Repository.new
|
|
14
|
-
|
|
15
|
-
unless Database.exists?(repo.git_dir)
|
|
16
|
-
$stderr.puts "Database not initialized. Run 'git pkgs init' first."
|
|
17
|
-
exit 1
|
|
18
|
-
end
|
|
16
|
+
require_database(repo)
|
|
19
17
|
|
|
20
18
|
Database.connect(repo.git_dir)
|
|
21
19
|
|
|
22
20
|
branch_name = @options[:branch] || repo.default_branch
|
|
23
21
|
branch = Models::Branch.find_by(name: branch_name)
|
|
24
22
|
|
|
25
|
-
unless branch&.last_analyzed_sha
|
|
26
|
-
$stderr.puts "No analysis found for branch '#{branch_name}'"
|
|
27
|
-
exit 1
|
|
28
|
-
end
|
|
23
|
+
error "No analysis found for branch '#{branch_name}'" unless branch&.last_analyzed_sha
|
|
29
24
|
|
|
30
25
|
current_commit = Models::Commit.find_by(sha: branch.last_analyzed_sha)
|
|
31
26
|
snapshots = current_commit&.dependency_snapshots&.includes(:manifest) || []
|
|
@@ -35,7 +30,7 @@ module Git
|
|
|
35
30
|
end
|
|
36
31
|
|
|
37
32
|
if snapshots.empty?
|
|
38
|
-
|
|
33
|
+
empty_result "No dependencies found"
|
|
39
34
|
return
|
|
40
35
|
end
|
|
41
36
|
|
|
@@ -72,10 +67,14 @@ module Git
|
|
|
72
67
|
end
|
|
73
68
|
|
|
74
69
|
if outdated_data.empty?
|
|
75
|
-
|
|
70
|
+
empty_result "All dependencies have been updated recently"
|
|
76
71
|
return
|
|
77
72
|
end
|
|
78
73
|
|
|
74
|
+
paginate { output_text(outdated_data) }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def output_text(outdated_data)
|
|
79
78
|
puts "Dependencies by last update:"
|
|
80
79
|
puts
|
|
81
80
|
|
|
@@ -93,7 +92,7 @@ module Git
|
|
|
93
92
|
options = {}
|
|
94
93
|
|
|
95
94
|
parser = OptionParser.new do |opts|
|
|
96
|
-
opts.banner = "Usage: git pkgs
|
|
95
|
+
opts.banner = "Usage: git pkgs stale [options]"
|
|
97
96
|
|
|
98
97
|
opts.on("-e", "--ecosystem=NAME", "Filter by ecosystem") do |v|
|
|
99
98
|
options[:ecosystem] = v
|
|
@@ -107,6 +106,10 @@ module Git
|
|
|
107
106
|
options[:days] = v
|
|
108
107
|
end
|
|
109
108
|
|
|
109
|
+
opts.on("--no-pager", "Do not pipe output into a pager") do
|
|
110
|
+
options[:no_pager] = true
|
|
111
|
+
end
|
|
112
|
+
|
|
110
113
|
opts.on("-h", "--help", "Show this help") do
|
|
111
114
|
puts opts
|
|
112
115
|
exit
|