mj 0.9.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 491af2ce87f053d61a6521c756d7f6b26947b1d92146d10845ead7aeda56fe92
4
- data.tar.gz: 7338045904d1fb8cba4a6d093a7155f9db9eddd0c07da5f966e405bca7902541
3
+ metadata.gz: 3ae71fd8808a2f04a8cfb7838d347f529a5df0aa9b5a3d6eb3618b089c9724c3
4
+ data.tar.gz: e8f7c0778fc83b5fe2e5206b14a84ba297f85c5337d3248d48ff36e5099bfa7b
5
5
  SHA512:
6
- metadata.gz: a5df4a249deffebe270dc9132fcc25c39b705594a9151a4133460908841cf534d9493a54167c3c006ae1a09f981b34819c090d9ce38fd521a0804ec33e0e6f18
7
- data.tar.gz: 3a924762bab7fde391373972169c99050c8d95d440bfc3a31044dcf9057513ea19c4e17b4091b02bc6af316b64c02db84117e79c1de08a231a2f3242fc9b6388
6
+ metadata.gz: 33aafd4dc0b0bc9910442c625b04da211b71fb86d82d2f2b13282fb3a3ded0a081ea3877d98eac8fc5c6b18a0532d90f6d59926c108b5c0b753a672d35d4ffe2
7
+ data.tar.gz: d9dfd28ccbdc9aa8e615d2fa1ef81d57ccc33707ea8c519fe0cfce55e2fc17b8fc1345d43da241e929da05a70c70fa11bf89376fd1e14beae6d4f895569ca44a
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mj (0.9.2)
4
+ mj (1.0.0)
5
5
  colorize
6
6
  koine-rest_client
7
7
  mj-hash_utils
data/README.md CHANGED
@@ -33,6 +33,12 @@ mj help
33
33
  ```
34
34
  bundle exec mj git checkout partial-branch-name # it will create a local branch if that is remote only
35
35
  bundle exec mj git checkout partial-branch-name --dry-run # if you want to see the command before executing
36
+
37
+ bundle exec mj git delete_stale_branches \
38
+ [--dry-run] \
39
+ [--only-with-prs] \
40
+ [--only-with-closed-prs] \
41
+ [--before-date=2021-01-01]
36
42
  ```
37
43
 
38
44
  ```
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "local_branch"
4
4
  require_relative "remote_branch"
5
+ require_relative "pull_request"
5
6
 
6
7
  module Mj
7
8
  module Git
@@ -43,6 +44,10 @@ module Mj
43
44
  @branches.each(&block)
44
45
  end
45
46
 
47
+ def sort_by(&block)
48
+ self.class.new(@branches.sort_by(&block))
49
+ end
50
+
46
51
  def length
47
52
  @branches.length
48
53
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mj
4
+ module Git
5
+ module Commands
6
+ class DeleteStaleBranchesCommand
7
+ def initialize(options: {})
8
+ @options = options
9
+ end
10
+
11
+ def dry_run?
12
+ @options[:dry_run]
13
+ end
14
+
15
+ def before_date
16
+ if @before_date
17
+ return @before_date
18
+ end
19
+
20
+ if @options[:before_date]
21
+ @before_date ||= DateTime.parse(@options[:before_date])
22
+ end
23
+
24
+ # Default to now, because all things happened before now.
25
+ @before_date ||= DateTime.now
26
+ end
27
+
28
+ def only_with_prs
29
+ @options[:only_with_prs]
30
+ end
31
+
32
+ def only_with_closed_prs
33
+ @options[:only_with_closed_prs]
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mj
4
+ module Git
5
+ module Commands
6
+ class DeleteStaleBranchesCommandHandler
7
+ def initialize(stdout:, command_executer: CommandExecuter.new)
8
+ @stdout = stdout
9
+ @command_executer = command_executer
10
+ end
11
+
12
+ def handle(command)
13
+ puts("Deleting stale branches", color: :blue)
14
+
15
+ list_command = "git branch -a"
16
+ list_command += " | grep remotes/ | grep -v '/HEAD'"
17
+
18
+ branches = Git::Branches
19
+ .from_branch_names(@command_executer.execute(list_command))
20
+ .sort_by(&:last_commit_date)
21
+
22
+ branches.each do |branch|
23
+ delete_branch(branch, command: command)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def delete_branch(branch, command:)
30
+ if delete?(branch, command: command)
31
+ puts("Deleting branch #{branch.name}", color: :green)
32
+
33
+ unless command.dry_run?
34
+ delete(branch)
35
+ end
36
+ end
37
+ end
38
+
39
+ def delete?(branch, command:) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
40
+ if %w[master main].include?(branch.to_local.name)
41
+ puts("Skipping #{branch.name}. No, no, no, no.", color: :red)
42
+ return false
43
+ end
44
+
45
+ if branch.last_commit_date >= command.before_date
46
+ puts("Skipping #{branch.name}. Not before #{command.before_date}", color: :yellow)
47
+ return false
48
+ end
49
+
50
+ 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
53
+ end
54
+
55
+ if command.only_with_closed_prs && !branch.pr.closed?
56
+ puts("Skipping #{branch.name}. PR not closed - state: #{branch.pr.state}.", color: :yellow)
57
+ return false
58
+ end
59
+
60
+ true
61
+ end
62
+
63
+ def delete(branch)
64
+ branch.delete
65
+ rescue StandardError => exception
66
+ log("Could not delete branch #{branch.name}: #{exception.message}", color: :red)
67
+ end
68
+
69
+ def puts(string, color: nil)
70
+ if color
71
+ string = string.colorize(color)
72
+ end
73
+
74
+ @stdout.puts(string)
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mj
4
+ module Git
5
+ class PullRequest
6
+ attr_reader :number
7
+ attr_reader :title
8
+ attr_reader :state
9
+ attr_reader :updated_at
10
+
11
+ def initialize(number:, title:, state:, updated_at:)
12
+ @number = number
13
+ @title = title
14
+ @state = state
15
+ @updated_at = updated_at
16
+ end
17
+
18
+ def closed?
19
+ state == "MERGED" || state == "CLOSED"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -5,14 +5,19 @@ module Mj
5
5
  class RemoteBranch
6
6
  attr_reader :name
7
7
 
8
- def initialize(name)
8
+ def initialize(name, command_executer: CommandExecuter.new)
9
9
  @name = name
10
+ @command_executer = command_executer
10
11
  end
11
12
 
12
13
  def checkout_command
13
14
  "git checkout -b #{local_branch_name} #{name}"
14
15
  end
15
16
 
17
+ def last_commit_date
18
+ @last_commit_date ||= DateTime.parse(@command_executer.execute("git log -1 --format=%cd #{name}").first)
19
+ end
20
+
16
21
  def length
17
22
  @name.length
18
23
  end
@@ -21,12 +26,51 @@ module Mj
21
26
  LocalBranch.new(local_branch_name)
22
27
  end
23
28
 
29
+ def has_pr?
30
+ !pr.nil?
31
+ end
32
+
33
+ # @return [Git::PullRequest]
34
+ def pr
35
+ if defined?(@pr)
36
+ return @pr
37
+ end
38
+
39
+ @pr ||= fetch_pr
40
+ end
41
+
42
+ def delete
43
+ @command_executer.execute("git push origin :#{local_branch_name}")
44
+ end
45
+
24
46
  private
25
47
 
26
48
  def local_branch_name
27
49
  pattern = %r{^remotes/\w+/}
28
50
  name.sub(pattern, "")
29
51
  end
52
+
53
+ def fetch_pr # rubocop:disable Metrics/MethodLength
54
+ data = @command_executer.execute(
55
+ "gh pr list --head #{local_branch_name} --state=all --json=number,state,title,updatedAt"
56
+ )
57
+
58
+ data = JSON.parse(data.join("")).first
59
+
60
+ if data.nil?
61
+ return
62
+ end
63
+
64
+ # I.E. ["14", "WIP on packer", "handle-packer-files", "DRAFT", "2022-03-14T20:14:17Z"]
65
+ Git::PullRequest.new(
66
+ number: data['number'],
67
+ title: data['title'],
68
+ state: data['state'],
69
+ updated_at: DateTime.parse(data['updatedAt'])
70
+ )
71
+ rescue StandardError
72
+ nil
73
+ end
30
74
  end
31
75
  end
32
76
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  require_relative "commands/checkout_command_handler"
4
4
  require_relative "commands/checkout_command"
5
+ require_relative "commands/delete_stale_branches_command_handler"
6
+ require_relative "commands/delete_stale_branches_command"
5
7
  require_relative "command_executer"
6
8
 
7
9
  module Mj
@@ -14,6 +16,29 @@ module Mj
14
16
  handler = Commands::CheckoutCommandHandler.new(stdout: $stdout)
15
17
  handler.handle(command)
16
18
  end
19
+
20
+ desc "delete_stale_branches", "Delete remote stale branches"
21
+ option :dry_run,
22
+ type: :boolean,
23
+ banner: "Just outputs, does not delete",
24
+ aliases: :d
25
+ option :only_with_prs,
26
+ type: :boolean,
27
+ banner: "Only branches that have PRs (Branch can be restored from PR page)",
28
+ aliases: :p
29
+ option :only_with_closed_prs,
30
+ type: :boolean,
31
+ banner: "Do not delete if PRs are in DRAFT or OPEN - will they maybe be merged?",
32
+ aliases: :c
33
+ option :before_date,
34
+ type: :string,
35
+ banner: "Formatted date YYY-MM-DD",
36
+ aliases: :b
37
+ def delete_stale_branches
38
+ command = Commands::DeleteStaleBranchesCommand.new(options: options)
39
+ handler = Commands::DeleteStaleBranchesCommandHandler.new(stdout: $stdout)
40
+ handler.handle(command)
41
+ end
17
42
  end
18
43
  end
19
44
  end
data/lib/mj/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mj
4
- VERSION = "0.9.2"
4
+ VERSION = "1.0.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: 0.9.2
4
+ version: 1.0.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-08-23 00:00:00.000000000 Z
11
+ date: 2024-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -137,7 +137,10 @@ files:
137
137
  - lib/mj/git/command_executer.rb
138
138
  - lib/mj/git/commands/checkout_command.rb
139
139
  - lib/mj/git/commands/checkout_command_handler.rb
140
+ - lib/mj/git/commands/delete_stale_branches_command.rb
141
+ - lib/mj/git/commands/delete_stale_branches_command_handler.rb
140
142
  - lib/mj/git/local_branch.rb
143
+ - lib/mj/git/pull_request.rb
141
144
  - lib/mj/git/remote_branch.rb
142
145
  - lib/mj/git/thor_command.rb
143
146
  - lib/mj/graphql/client.rb
@@ -159,7 +162,7 @@ metadata:
159
162
  source_code_uri: https://github.com/mjacobus/mj
160
163
  changelog_uri: https://github.com/mjacobus/mj/blob/main/CHANGELOG.md
161
164
  rubygems_mfa_required: 'true'
162
- post_install_message:
165
+ post_install_message:
163
166
  rdoc_options: []
164
167
  require_paths:
165
168
  - lib
@@ -174,8 +177,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
174
177
  - !ruby/object:Gem::Version
175
178
  version: '0'
176
179
  requirements: []
177
- rubygems_version: 3.5.14
178
- signing_key:
180
+ rubygems_version: 3.4.10
181
+ signing_key:
179
182
  specification_version: 4
180
183
  summary: My personal CLI
181
184
  test_files: []