semmy 1.2.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a9c4378a310880351973ba7495052ba8732629137915052be599823e74436c5
4
- data.tar.gz: f3225ce6b30493cd39ca8b53a1751367874bb4cc195944eaeefd9c8b3881f31d
3
+ metadata.gz: ce09082714dcb3d35eb9667425bf29167c3d3a768138b272a7b09af7ff592343
4
+ data.tar.gz: 819dd6a572482aced62c3a3b80ab28d4af69a09276401cca60f0536df602194d
5
5
  SHA512:
6
- metadata.gz: bdc2c3cb16604b4204a69de93c0b6d362487d743943e7d8da4bb40073fc4efcdef4d00b1fabf75a5311966edcd884607fcaf310545842a38f76a3517592fcfd4
7
- data.tar.gz: 3ca48dbd6d46c1ef27c493f0d45404344ee13bbb6a2258029ecf6dea8eed8bc7d462f7a7051380ccf59f3bff041038c7b4b6c75ae32819ad7b6b08cb649cd1bb
6
+ metadata.gz: f4e4fb1222c83d1e94ccf400719c36d21501fb1f4219cae6a314ce389fce167bbeb2f5a881fc0cf2bf7fe42c72ee63e2fbaec43a7e5a89cf83528bd589884925
7
+ data.tar.gz: 6bbcad0f49ab3726535dde84915a57f139708ebefd97fe1879dc8e1a97c22a6c051162c0ee4279bdb76df4bd4c793fc0805e56886776dc85db09963aedf6368f
data/CHANGELOG.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # CHANGELOG
2
2
 
3
- ### Version 1.2.0
3
+ ### Version 1.3.0
4
4
 
5
- 2019-01-24
5
+ 2026-09-11
6
6
 
7
- [Compare changes](https://github.com/tf/semmy/compare/1-1-stable...v1.2.0)
7
+ [Compare changes](https://github.com/tf/semmy/compare/1-2-stable...v1.3.0)
8
8
 
9
- - Add config option to automatically push branches after release.
9
+ - Support releasing from Jujutsu repositories.
10
10
 
11
11
  See
12
- [1-1-stable branch](https://github.com/tf/semmy/blob/1-1-stable/CHANGELOG.md)
12
+ [1-2-stable branch](https://github.com/tf/semmy/blob/1-2-stable/CHANGELOG.md)
13
13
  for previous changes.
data/README.md CHANGED
@@ -21,6 +21,28 @@ tags.
21
21
  Patch level versions are released via backports to the stable
22
22
  branches.
23
23
 
24
+ ### Jujutsu Repositories
25
+
26
+ Semmy detects a `.jj` directory and drives
27
+ [Jujutsu](https://jj-vcs.github.io/jj/) instead of Git. Bookmarks take
28
+ the place of branches: since jj has no checked out branch, the
29
+ bookmark of the closest ancestor commit is used and the commit tasks
30
+ move it forward explicitly. The release branch is resolved once per
31
+ rake run, before `branches:create_stable` places a second bookmark on
32
+ the same commit.
33
+
34
+ Bundler's `release` task shells out to Git, and colocated jj
35
+ repositories leave `HEAD` detached, which would make its push step
36
+ fail with `src refspec refs/heads/HEAD does not match any`. Semmy
37
+ attaches `HEAD` to the release branch in a prerequisite of Bundler's
38
+ `release:source_control_push` task. Only the ref is moved, never the
39
+ working copy, and jj detaches `HEAD` again on its next working copy
40
+ update.
41
+
42
+ This requires the working copy commit to sit directly on top of the
43
+ release branch. Otherwise the release aborts with a hint to run
44
+ `jj new master`.
45
+
24
46
  ### Version Suffix
25
47
 
26
48
  The version in the gem's version file is increased in a separate
@@ -0,0 +1,34 @@
1
+ require 'git'
2
+
3
+ module Semmy
4
+ module Scm
5
+ module Git
6
+ extend self
7
+
8
+ def current_branch
9
+ repository.current_branch
10
+ end
11
+
12
+ def commit_all(message, _branch)
13
+ repository.commit_all(message)
14
+ end
15
+
16
+ def create_branch(name, _base)
17
+ repository.branch(name).create
18
+ end
19
+
20
+ def push(remote, name)
21
+ repository.push(remote, name)
22
+ end
23
+
24
+ def attach_git_head(_branch)
25
+ end
26
+
27
+ private
28
+
29
+ def repository
30
+ ::Git.open('.')
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,85 @@
1
+ require 'open3'
2
+
3
+ module Semmy
4
+ module Scm
5
+ module Jj
6
+ extend self
7
+
8
+ class CommandFailed < Error; end
9
+ class BookmarkNotFound < Error; end
10
+ class GitHeadMismatch < Error; end
11
+
12
+ def current_branch
13
+ jj('log', '--no-graph',
14
+ '--revisions', 'heads(::@ & bookmarks())',
15
+ '--template', 'local_bookmarks.map(|bookmark| bookmark.name()).join("\n")')
16
+ .split("\n").first
17
+ end
18
+
19
+ def commit_all(message, branch)
20
+ bookmark = required_bookmark(branch)
21
+
22
+ jj('commit', '--message', message)
23
+ jj('bookmark', 'set', bookmark, '--revision', '@-')
24
+ end
25
+
26
+ def create_branch(name, base)
27
+ jj('bookmark', 'create', name, '--revision', required_bookmark(base))
28
+ end
29
+
30
+ def push(remote, name)
31
+ unless bookmark?(name)
32
+ fail(BookmarkNotFound, "Bookmark #{name} does not exist.")
33
+ end
34
+
35
+ jj('git', 'push', '--remote', remote, '--bookmark', name)
36
+ end
37
+
38
+ def attach_git_head(branch)
39
+ bookmark = required_bookmark(branch)
40
+ reference = "refs/heads/#{bookmark}"
41
+
42
+ unless git('rev-parse', 'HEAD') == git('rev-parse', reference)
43
+ fail(GitHeadMismatch,
44
+ "Git HEAD is not at #{bookmark}. " \
45
+ "Run `jj new #{bookmark}` before releasing.")
46
+ end
47
+
48
+ Shell.info("Attaching git HEAD to #{bookmark}.")
49
+ git('symbolic-ref', 'HEAD', reference)
50
+ end
51
+
52
+ private
53
+
54
+ def required_bookmark(name)
55
+ name ||
56
+ fail(BookmarkNotFound,
57
+ 'No bookmark found in ancestors of working copy commit.')
58
+ end
59
+
60
+ def bookmark?(name)
61
+ !jj('bookmark', 'list', '--template', 'name ++ "\n"', name).strip.empty?
62
+ end
63
+
64
+ def jj(*args)
65
+ run('jj', *args)
66
+ end
67
+
68
+ def git(*args)
69
+ run('git', *args)
70
+ end
71
+
72
+ def run(command, *args)
73
+ stdout, stderr, status = Open3.capture3(command, *args)
74
+
75
+ unless status.success?
76
+ fail(CommandFailed,
77
+ "Command `#{command} #{args.join(' ')}` failed:\n#{stderr}")
78
+ end
79
+
80
+ Shell.sub_process_output(stderr.chomp) unless stderr.empty?
81
+ stdout
82
+ end
83
+ end
84
+ end
85
+ end
data/lib/semmy/scm.rb CHANGED
@@ -1,17 +1,46 @@
1
+ require 'pathname'
2
+
3
+ require 'semmy/scm/git'
4
+ require 'semmy/scm/jj'
5
+
1
6
  module Semmy
2
7
  module Scm
3
8
  extend self
4
9
 
5
10
  def on_master?
6
- git.current_branch == 'master'
11
+ release_branch == 'master'
7
12
  end
8
13
 
9
14
  def on_minor_version_stable?(stable_branch_name)
10
- !!git.current_branch.match(stable_branch_matcher(stable_branch_name))
15
+ !!release_branch.to_s.match(stable_branch_matcher(stable_branch_name))
11
16
  end
12
17
 
13
18
  def on_major_version_stable?(stable_branch_name)
14
- !!git.current_branch.match(major_version_stable_branch_matcher(stable_branch_name))
19
+ !!release_branch.to_s.match(major_version_stable_branch_matcher(stable_branch_name))
20
+ end
21
+
22
+ def commit_all(message)
23
+ repository.commit_all(message, release_branch)
24
+ end
25
+
26
+ def create_branch(name)
27
+ repository.create_branch(name, release_branch)
28
+ end
29
+
30
+ def push(remote, name)
31
+ repository.push(remote, name)
32
+ end
33
+
34
+ def attach_git_head
35
+ repository.attach_git_head(release_branch)
36
+ end
37
+
38
+ def release_branch
39
+ @release_branch ||= repository.current_branch
40
+ end
41
+
42
+ def reset
43
+ @release_branch = nil
15
44
  end
16
45
 
17
46
  private
@@ -24,8 +53,13 @@ module Semmy
24
53
  Regexp.new(stable_branch_name.gsub(/%\{\w+\}/, '[0-9]+'))
25
54
  end
26
55
 
27
- def git
28
- Git.open('.')
56
+ def repository
57
+ Pathname.pwd.ascend do |directory|
58
+ return Jj if directory.join('.jj').directory?
59
+ return Git if directory.join('.git').exist?
60
+ end
61
+
62
+ Git
29
63
  end
30
64
  end
31
65
  end
@@ -1,5 +1,3 @@
1
- require 'git'
2
-
3
1
  module Semmy
4
2
  module Tasks
5
3
  class Branches < Base
@@ -8,7 +6,7 @@ module Semmy
8
6
  task 'create_stable' do
9
7
  Shell.info("Creating stable branch #{stable_branch_name}.")
10
8
 
11
- git.branch(stable_branch_name).create
9
+ Scm.create_branch(stable_branch_name)
12
10
  end
13
11
 
14
12
  task 'push_master', [:remote] do |_, args|
@@ -18,6 +16,10 @@ module Semmy
18
16
  task 'push_previous_stable', [:remote] do |_, args|
19
17
  push_branch(args[:remote], previous_stable_branch_name)
20
18
  end
19
+
20
+ task 'attach_git_head' do
21
+ Scm.attach_git_head
22
+ end
21
23
  end
22
24
  end
23
25
 
@@ -38,15 +40,11 @@ module Semmy
38
40
 
39
41
  if config.push_branches_after_release
40
42
  Shell.info("Pushing #{name} to #{remote}.")
41
- git.push(remote, name)
43
+ Scm.push(remote, name)
42
44
  else
43
45
  Shell.info("NOTE: Remember to push #{name} to #{remote}.")
44
46
  end
45
47
  end
46
-
47
- def git
48
- Git.open('.')
49
- end
50
48
  end
51
49
  end
52
50
  end
@@ -1,5 +1,3 @@
1
- require 'git'
2
-
3
1
  module Semmy
4
2
  module Tasks
5
3
  class Commit < Base
@@ -8,7 +6,7 @@ module Semmy
8
6
  task 'prepare' do
9
7
  Shell.info('Creating prepare commit.')
10
8
 
11
- git.commit_all(config.prepare_commit_message % {
9
+ Scm.commit_all(config.prepare_commit_message % {
12
10
  version: Project.version
13
11
  })
14
12
  end
@@ -16,15 +14,11 @@ module Semmy
16
14
  task 'bump' do
17
15
  Shell.info('Creating bump commit.')
18
16
 
19
- git.commit_all(config.bump_commit_message % {
17
+ Scm.commit_all(config.bump_commit_message % {
20
18
  version: Project.version
21
19
  })
22
20
  end
23
21
  end
24
-
25
- def git
26
- Git.open('.')
27
- end
28
22
  end
29
23
  end
30
24
  end
data/lib/semmy/tasks.rb CHANGED
@@ -26,6 +26,8 @@ module Semmy
26
26
  Branches.new(config)
27
27
  end
28
28
 
29
+ task 'release:source_control_push' => 'semmy:branches:attach_git_head'
30
+
29
31
  desc 'Prepare minor or major release'
30
32
  task 'release:prepare:master' => [
31
33
  'semmy:versioning:remove_development_version_suffix',
data/lib/semmy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Semmy
2
- VERSION = '1.2.0'
2
+ VERSION = '1.3.0'
3
3
  end
data/semmy.gemspec CHANGED
@@ -22,8 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.add_dependency 'unindent', '~> 1.0'
23
23
  spec.add_dependency 'rainbow', '~> 2.1'
24
24
 
25
- spec.add_development_dependency 'bundler', '~> 1.10'
26
- spec.add_development_dependency 'rake', '~> 11.0'
25
+ spec.add_development_dependency 'rake', '~> 13.0'
27
26
  spec.add_development_dependency 'rspec', '~> 3.0'
28
27
  spec.add_development_dependency 'rubocop', '~> 0.42.0'
29
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: semmy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Fischbach
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-24 00:00:00.000000000 Z
11
+ date: 2026-09-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: git
@@ -52,34 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '2.1'
55
- - !ruby/object:Gem::Dependency
56
- name: bundler
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.10'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.10'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: rake
71
57
  requirement: !ruby/object:Gem::Requirement
72
58
  requirements:
73
59
  - - "~>"
74
60
  - !ruby/object:Gem::Version
75
- version: '11.0'
61
+ version: '13.0'
76
62
  type: :development
77
63
  prerelease: false
78
64
  version_requirements: !ruby/object:Gem::Requirement
79
65
  requirements:
80
66
  - - "~>"
81
67
  - !ruby/object:Gem::Version
82
- version: '11.0'
68
+ version: '13.0'
83
69
  - !ruby/object:Gem::Dependency
84
70
  name: rspec
85
71
  requirement: !ruby/object:Gem::Requirement
@@ -108,7 +94,7 @@ dependencies:
108
94
  - - "~>"
109
95
  - !ruby/object:Gem::Version
110
96
  version: 0.42.0
111
- description:
97
+ description:
112
98
  email:
113
99
  - mail@timfischbach.de
114
100
  executables: []
@@ -140,6 +126,8 @@ files:
140
126
  - lib/semmy/project.rb
141
127
  - lib/semmy/ruby_gems.rb
142
128
  - lib/semmy/scm.rb
129
+ - lib/semmy/scm/git.rb
130
+ - lib/semmy/scm/jj.rb
143
131
  - lib/semmy/shell.rb
144
132
  - lib/semmy/tasks.rb
145
133
  - lib/semmy/tasks/base.rb
@@ -157,7 +145,7 @@ homepage: https://github.com/tf/semmy
157
145
  licenses:
158
146
  - MIT
159
147
  metadata: {}
160
- post_install_message:
148
+ post_install_message:
161
149
  rdoc_options: []
162
150
  require_paths:
163
151
  - lib
@@ -172,9 +160,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
172
160
  - !ruby/object:Gem::Version
173
161
  version: '0'
174
162
  requirements: []
175
- rubyforge_project:
176
- rubygems_version: 2.7.5
177
- signing_key:
163
+ rubygems_version: 3.4.19
164
+ signing_key:
178
165
  specification_version: 4
179
166
  summary: Rake tasks for a semantic versioning of gems
180
167
  test_files: []