mj 1.0.1 → 1.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de854df996b9ec36033b49f7d985e7ccc01a7c0e57c1d1facc62128623ecbda1
4
- data.tar.gz: 8525e716e78a261741fae76f10b3e56cc87e6c61d456ebe66b3aa654fb60122a
3
+ metadata.gz: 719a1dd98c88afa768cf64e3f898ef95535a2b11a1322bad42dd3adaa31cd378
4
+ data.tar.gz: 17980273bfabcf5b9b2378f7e0687de5c3fd2b4df412caa101ace15aab3ce266
5
5
  SHA512:
6
- metadata.gz: 1b170449ed5da0e13b54f29f8bfd92c6b928f85882a03f726211bfcb8ad5fb3d6e9b6af27eff1aaeac822ca183b35e7e93f1728993df2f374331bfab80ca6b5e
7
- data.tar.gz: 53023f5352259df180d522286f513eb3804f8632465c2eb53dc5b3ebaa812e133ba6a15346290e65bb5c33aa002677127e8082591847d42df36d6b60b49a0fc7
6
+ metadata.gz: 652fb4a8eb141689c29acfffb70666f1a17ca3acad33a888cd5e86ce2728def89959f3543cebd36e3587cd4227fc7166c7f677657ed9b20ee6b445b4f904fd8e
7
+ data.tar.gz: 1c9027cbde6e702272eee45edbbf5ad06392e527b32ff37454155541c455d5127a7013308dc38db414b78f4ef8b5d7ecd6c578f9d22b066ddfcb1c140d521f73
data/.rubocop.yml CHANGED
@@ -66,6 +66,9 @@ Style/GuardClause:
66
66
  Style/IfUnlessModifier:
67
67
  Enabled: false
68
68
 
69
+ Style/NegatedIf:
70
+ Enabled: false
71
+
69
72
  Style/StringLiterals:
70
73
  Enabled: true
71
74
  EnforcedStyle: double_quotes
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mj (1.0.1)
4
+ mj (1.2.0)
5
5
  colorize
6
6
  koine-rest_client
7
7
  mj-hash_utils
@@ -111,7 +111,7 @@ GEM
111
111
  strscan (3.1.0)
112
112
  thor (1.2.2)
113
113
  unicode-display_width (2.5.0)
114
- uri (0.13.0)
114
+ uri (0.13.1)
115
115
 
116
116
  PLATFORMS
117
117
  arm64-darwin-23
data/README.md CHANGED
@@ -38,6 +38,9 @@ bundle exec mj git delete_stale_branches \
38
38
  [--dry-run] \
39
39
  [--only-with-prs] \
40
40
  [--only-with-closed-prs] \
41
+ [--from-commiters=emal@one,email@two] \
42
+ [--from-pull_requestors=mjacobus,other-gh-username] \
43
+ [--after-date=2021-01-01] \
41
44
  [--before-date=2021-01-01]
42
45
  ```
43
46
 
@@ -3,6 +3,7 @@
3
3
  require_relative "local_branch"
4
4
  require_relative "remote_branch"
5
5
  require_relative "pull_request"
6
+ require_relative "pull_request_author"
6
7
 
7
8
  module Mj
8
9
  module Git
@@ -12,6 +12,19 @@ module Mj
12
12
  @options[:dry_run]
13
13
  end
14
14
 
15
+ def after_date
16
+ if @after_date
17
+ return @after_date
18
+ end
19
+
20
+ if @options[:after_date]
21
+ @after_date ||= DateTime.parse(@options[:after_date])
22
+ end
23
+
24
+ # Default to 100+ years ago - sure there are no commits that old
25
+ @after_date ||= DateTime.new(1900, 1, 1, 0, 0, 0)
26
+ end
27
+
15
28
  def before_date
16
29
  if @before_date
17
30
  return @before_date
@@ -32,6 +45,14 @@ module Mj
32
45
  def only_with_closed_prs
33
46
  @options[:only_with_closed_prs]
34
47
  end
48
+
49
+ def from_pull_requestors
50
+ @options[:from_pull_requestors].to_s.split(",")
51
+ end
52
+
53
+ def from_commiters
54
+ @options[:from_commiters].to_s.split(",")
55
+ end
35
56
  end
36
57
  end
37
58
  end
@@ -28,7 +28,7 @@ module Mj
28
28
 
29
29
  def delete_branch(branch, command:)
30
30
  if delete?(branch, command: command)
31
- puts("Deleting branch #{branch.name}", color: :green)
31
+ puts("Deleting branch #{branch.name} \t| #{branch.summary}", color: :green)
32
32
 
33
33
  unless command.dry_run?
34
34
  delete(branch)
@@ -36,24 +36,35 @@ module Mj
36
36
  end
37
37
  end
38
38
 
39
- def delete?(branch, command:) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
39
+ def delete?(branch, command:) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
40
40
  if %w[master main].include?(branch.to_local.name)
41
- puts("Skipping #{branch.name}. No, no, no, no.", color: :red)
41
+ puts("Skipping #{branch.summary}. No, no, no, no.", color: :red)
42
42
  return false
43
43
  end
44
44
 
45
45
  if branch.last_commit_date >= command.before_date
46
- puts("Skipping #{branch.name}. Not before #{command.before_date}", color: :yellow)
46
+ return cannot_delete(branch, "Not before #{command.before_date}.")
47
+ end
48
+
49
+ if branch.last_commit_date < command.after_date
50
+ return cannot_delete(branch, "Not after #{command.after_date}.")
51
+ end
52
+
53
+ unless commiter_check(command, branch)
47
54
  return false
48
55
  end
49
56
 
57
+ # PR checks later - more efficient. May not have to check them if any of the above is falsy
58
+
50
59
  if (command.only_with_prs || command.only_with_closed_prs) && branch.pr.nil?
51
- puts("Skipping #{branch.name}. Does not have PR.", color: :yellow)
52
- return false
60
+ return cannot_delete(branch, "Does not have a PR")
53
61
  end
54
62
 
55
63
  if command.only_with_closed_prs && !branch.pr.closed?
56
- puts("Skipping #{branch.name}. PR not closed - state: #{branch.pr.state}.", color: :yellow)
64
+ return cannot_delete(branch, "PR not closed - state: #{branch.pr.state}.")
65
+ end
66
+
67
+ unless pull_request_author_check(command, branch)
57
68
  return false
58
69
  end
59
70
 
@@ -63,7 +74,37 @@ module Mj
63
74
  def delete(branch)
64
75
  branch.delete
65
76
  rescue Mj::Git::CommandExecuter::Error => exception
66
- puts("Could not delete branch #{branch.name}: #{exception.message}", color: :red)
77
+ puts("Could not delete branch #{branch.name}: #{exception.message}.", color: :red)
78
+ end
79
+
80
+ def cannot_delete(branch, reason)
81
+ puts("Skipping #{branch.name} \t| #{reason}.", color: :yellow)
82
+
83
+ false
84
+ end
85
+
86
+ def pull_request_author_check(command, branch)
87
+ if command.from_pull_requestors.empty?
88
+ return true
89
+ end
90
+
91
+ if branch.has_pr? && command.from_pull_requestors.include?(branch.pr.author.login)
92
+ return true
93
+ end
94
+
95
+ cannot_delete(branch, "PR not from pull requestors: #{command.from_pull_requestors.join(", ")}.")
96
+ end
97
+
98
+ def commiter_check(command, branch)
99
+ if command.from_commiters.empty?
100
+ return true
101
+ end
102
+
103
+ if command.from_commiters.map(&:downcase).include?(branch.last_commiter_email.downcase)
104
+ return true
105
+ end
106
+
107
+ cannot_delete(branch, "PR not from commiters: #{command.from_commiters.join(", ")}.")
67
108
  end
68
109
 
69
110
  def puts(string, color: nil)
@@ -5,14 +5,16 @@ module Mj
5
5
  class PullRequest
6
6
  attr_reader :number
7
7
  attr_reader :title
8
+ attr_reader :author
8
9
  attr_reader :state
9
10
  attr_reader :updated_at
10
11
 
11
- def initialize(number:, title:, state:, updated_at:)
12
+ def initialize(number:, title:, state:, updated_at:, author:)
12
13
  @number = number
13
14
  @title = title
14
15
  @state = state
15
16
  @updated_at = updated_at
17
+ @author = author
16
18
  end
17
19
 
18
20
  def closed?
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mj
4
+ module Git
5
+ class PullRequestAuthor
6
+ attr_reader :id
7
+ attr_reader :name
8
+ attr_reader :login
9
+ attr_reader :is_bot
10
+
11
+ def initialize(id:, name:, login:, is_bot:)
12
+ @id = id
13
+ @login = login
14
+ @name = name
15
+ @is_bot = is_bot
16
+ end
17
+ end
18
+ end
19
+ end
@@ -18,6 +18,14 @@ module Mj
18
18
  @last_commit_date ||= DateTime.parse(@command_executer.execute("git log -1 --format=%cd #{name}").first)
19
19
  end
20
20
 
21
+ def last_commiter_name
22
+ @last_commiter_name ||= @command_executer.execute("git log -1 --pretty=format:'%an' #{name}").first
23
+ end
24
+
25
+ def last_commiter_email
26
+ @last_commiter_email ||= @command_executer.execute("git log -1 --pretty=format:'%ae' #{name}").first
27
+ end
28
+
21
29
  def length
22
30
  @name.length
23
31
  end
@@ -30,6 +38,18 @@ module Mj
30
38
  !pr.nil?
31
39
  end
32
40
 
41
+ def summary
42
+ parts = []
43
+
44
+ parts << "Last Commited by #{last_commiter_name} (#{last_commiter_email}) on #{last_commit_date.strftime("%Y-%m-%d")}"
45
+
46
+ if @pr
47
+ parts << "PR ##{pr.number} by #{pr.author.login}"
48
+ end
49
+
50
+ parts.join(", ")
51
+ end
52
+
33
53
  # @return [Git::PullRequest]
34
54
  def pr
35
55
  if defined?(@pr)
@@ -50,12 +70,12 @@ module Mj
50
70
  name.sub(pattern, "")
51
71
  end
52
72
 
53
- def fetch_pr # rubocop:disable Metrics/MethodLength
73
+ def fetch_pr # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
54
74
  data = @command_executer.execute(
55
- "gh pr list --head #{local_branch_name} --state=all --json=number,state,title,updatedAt"
75
+ "gh pr list --head #{local_branch_name} --state=all --json=number,state,title,updatedAt,author"
56
76
  )
57
77
 
58
- data = JSON.parse(data.join("")).first
78
+ data = JSON.parse(data.join).first
59
79
 
60
80
  if data.nil?
61
81
  return
@@ -63,10 +83,16 @@ module Mj
63
83
 
64
84
  # I.E. ["14", "WIP on packer", "handle-packer-files", "DRAFT", "2022-03-14T20:14:17Z"]
65
85
  Git::PullRequest.new(
66
- number: data['number'],
67
- title: data['title'],
68
- state: data['state'],
69
- updated_at: DateTime.parse(data['updatedAt'])
86
+ number: data["number"],
87
+ title: data["title"],
88
+ state: data["state"],
89
+ updated_at: DateTime.parse(data["updatedAt"]),
90
+ author: PullRequestAuthor.new(
91
+ id: data.dig("author", "id"),
92
+ name: data.dig("author", "name"),
93
+ is_bot: data.dig("author", "is_bot"),
94
+ login: data.dig("author", "login")
95
+ )
70
96
  )
71
97
  rescue StandardError
72
98
  nil
@@ -30,10 +30,22 @@ module Mj
30
30
  type: :boolean,
31
31
  banner: "Do not delete if PRs are in DRAFT or OPEN - will they maybe be merged?",
32
32
  aliases: :c
33
+ option :after_date,
34
+ type: :string,
35
+ banner: "Formatted date YYY-MM-DD",
36
+ aliases: :a
33
37
  option :before_date,
34
38
  type: :string,
35
39
  banner: "Formatted date YYY-MM-DD",
36
40
  aliases: :b
41
+ option :from_pull_requestors,
42
+ type: :string,
43
+ banner: "Comma separated github usernames",
44
+ aliases: :u
45
+ option :from_commiters,
46
+ type: :string,
47
+ banner: "Comma separated commiter emails - assumes last commiter",
48
+ aliases: :e
37
49
  def delete_stale_branches
38
50
  command = Commands::DeleteStaleBranchesCommand.new(options: options)
39
51
  handler = Commands::DeleteStaleBranchesCommandHandler.new(stdout: $stdout)
data/lib/mj/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mj
4
- VERSION = "1.0.1"
4
+ VERSION = "1.2.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mj
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcelo Jacobus
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-12-05 00:00:00.000000000 Z
11
+ date: 2024-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -141,6 +141,7 @@ files:
141
141
  - lib/mj/git/commands/delete_stale_branches_command_handler.rb
142
142
  - lib/mj/git/local_branch.rb
143
143
  - lib/mj/git/pull_request.rb
144
+ - lib/mj/git/pull_request_author.rb
144
145
  - lib/mj/git/remote_branch.rb
145
146
  - lib/mj/git/thor_command.rb
146
147
  - lib/mj/graphql/client.rb
@@ -162,7 +163,7 @@ metadata:
162
163
  source_code_uri: https://github.com/mjacobus/mj
163
164
  changelog_uri: https://github.com/mjacobus/mj/blob/main/CHANGELOG.md
164
165
  rubygems_mfa_required: 'true'
165
- post_install_message:
166
+ post_install_message:
166
167
  rdoc_options: []
167
168
  require_paths:
168
169
  - lib
@@ -177,8 +178,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
177
178
  - !ruby/object:Gem::Version
178
179
  version: '0'
179
180
  requirements: []
180
- rubygems_version: 3.4.10
181
- signing_key:
181
+ rubygems_version: 3.5.14
182
+ signing_key:
182
183
  specification_version: 4
183
184
  summary: My personal CLI
184
185
  test_files: []