leg 0.0.1 → 0.0.2

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.
Files changed (78) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +10 -0
  3. data/CODE_OF_CONDUCT.md +74 -0
  4. data/Gemfile +6 -0
  5. data/Gemfile.lock +34 -0
  6. data/LICENSE +21 -0
  7. data/README.md +59 -0
  8. data/Rakefile +11 -0
  9. data/TUTORIAL.md +243 -0
  10. data/bin/console +9 -0
  11. data/bin/setup +6 -0
  12. data/exe/leg +6 -0
  13. data/leg.gemspec +31 -0
  14. data/lib/leg.rb +27 -0
  15. data/lib/leg/cli.rb +42 -0
  16. data/lib/leg/commands.rb +19 -0
  17. data/lib/leg/commands/amend.rb +49 -0
  18. data/lib/leg/commands/base_command.rb +99 -0
  19. data/lib/leg/commands/build.rb +126 -0
  20. data/lib/leg/commands/commit.rb +48 -0
  21. data/lib/leg/commands/diff.rb +29 -0
  22. data/lib/leg/commands/help.rb +43 -0
  23. data/lib/leg/commands/init.rb +46 -0
  24. data/lib/leg/commands/reset.rb +26 -0
  25. data/lib/leg/commands/resolve.rb +31 -0
  26. data/lib/leg/commands/save.rb +31 -0
  27. data/lib/leg/commands/status.rb +54 -0
  28. data/lib/leg/commands/step.rb +31 -0
  29. data/lib/leg/config.rb +42 -0
  30. data/lib/leg/default_templates.rb +340 -0
  31. data/lib/leg/diff.rb +151 -0
  32. data/lib/leg/diff_transformers.rb +11 -0
  33. data/lib/leg/diff_transformers/base_transformer.rb +13 -0
  34. data/lib/leg/diff_transformers/fold_sections.rb +89 -0
  35. data/lib/leg/diff_transformers/omit_adjacent_removals.rb +38 -0
  36. data/lib/leg/diff_transformers/syntax_highlight.rb +32 -0
  37. data/lib/leg/diff_transformers/trim_blank_lines.rb +25 -0
  38. data/lib/leg/line.rb +83 -0
  39. data/lib/leg/markdown.rb +20 -0
  40. data/lib/leg/page.rb +27 -0
  41. data/lib/leg/representations.rb +9 -0
  42. data/lib/leg/representations/base_representation.rb +42 -0
  43. data/lib/leg/representations/git.rb +388 -0
  44. data/lib/leg/representations/litdiff.rb +85 -0
  45. data/lib/leg/step.rb +16 -0
  46. data/lib/leg/template.rb +95 -0
  47. data/lib/leg/tutorial.rb +49 -0
  48. data/lib/leg/version.rb +3 -0
  49. metadata +112 -38
  50. data/bin/leg +0 -9
  51. data/lib/snaptoken.rb +0 -24
  52. data/lib/snaptoken/cli.rb +0 -61
  53. data/lib/snaptoken/commands.rb +0 -13
  54. data/lib/snaptoken/commands/amend.rb +0 -27
  55. data/lib/snaptoken/commands/base_command.rb +0 -92
  56. data/lib/snaptoken/commands/build.rb +0 -107
  57. data/lib/snaptoken/commands/commit.rb +0 -27
  58. data/lib/snaptoken/commands/help.rb +0 -38
  59. data/lib/snaptoken/commands/resolve.rb +0 -27
  60. data/lib/snaptoken/commands/status.rb +0 -21
  61. data/lib/snaptoken/commands/step.rb +0 -35
  62. data/lib/snaptoken/default_templates.rb +0 -287
  63. data/lib/snaptoken/diff.rb +0 -180
  64. data/lib/snaptoken/diff_line.rb +0 -54
  65. data/lib/snaptoken/diff_transformers.rb +0 -9
  66. data/lib/snaptoken/diff_transformers/base_transformer.rb +0 -9
  67. data/lib/snaptoken/diff_transformers/fold_sections.rb +0 -85
  68. data/lib/snaptoken/diff_transformers/omit_adjacent_removals.rb +0 -28
  69. data/lib/snaptoken/diff_transformers/trim_blank_lines.rb +0 -21
  70. data/lib/snaptoken/markdown.rb +0 -18
  71. data/lib/snaptoken/page.rb +0 -64
  72. data/lib/snaptoken/representations.rb +0 -8
  73. data/lib/snaptoken/representations/base_representation.rb +0 -38
  74. data/lib/snaptoken/representations/git.rb +0 -262
  75. data/lib/snaptoken/representations/litdiff.rb +0 -81
  76. data/lib/snaptoken/step.rb +0 -27
  77. data/lib/snaptoken/template.rb +0 -53
  78. data/lib/snaptoken/tutorial.rb +0 -64
@@ -1,54 +0,0 @@
1
- class Snaptoken::DiffLine
2
- TYPES = [:added, :removed, :unchanged, :folded]
3
-
4
- attr_reader :type, :source, :line_numbers
5
- attr_writer :source, :line_numbers
6
-
7
- def initialize(type, source, line_numbers)
8
- unless TYPES.include? type
9
- raise ArgumentError, "type must be one of: #{TYPES.inspect}"
10
- end
11
- @type = type
12
- @source = source.chomp
13
- @line_numbers = line_numbers
14
- end
15
-
16
- def clone
17
- Snaptoken::DiffLine.new(@type, @source.dup, @line_numbers.dup)
18
- end
19
-
20
- def type=(type)
21
- unless TYPES.include? type
22
- raise ArgumentError, "type must be one of: #{TYPES.inspect}"
23
- end
24
- @type = type
25
- end
26
-
27
- def blank?
28
- @source.strip.empty?
29
- end
30
-
31
- def line_number
32
- case @type
33
- when :removed, :folded
34
- @line_numbers[0]
35
- when :added, :unchanged
36
- @line_numbers[1]
37
- end
38
- end
39
-
40
- def to_patch(options = {})
41
- options[:unchanged_char] ||= " "
42
-
43
- case @type
44
- when :added
45
- "+#{@source}\n"
46
- when :removed
47
- "-#{@source}\n"
48
- when :unchanged
49
- "#{options[:unchanged_char]}#{@source}\n"
50
- when :folded
51
- raise "can't convert folded line to patch"
52
- end
53
- end
54
- end
@@ -1,9 +0,0 @@
1
- module Snaptoken::DiffTransformers
2
- end
3
-
4
- require 'snaptoken/diff_transformers/base_transformer'
5
-
6
- require 'snaptoken/diff_transformers/fold_sections'
7
- require 'snaptoken/diff_transformers/omit_adjacent_removals'
8
- require 'snaptoken/diff_transformers/trim_blank_lines'
9
-
@@ -1,9 +0,0 @@
1
- class Snaptoken::DiffTransformers::BaseTransformer
2
- def initialize(options = {})
3
- @options = options
4
- end
5
-
6
- def transform(diff)
7
- raise NotImplementedError
8
- end
9
- end
@@ -1,85 +0,0 @@
1
- class Snaptoken::DiffTransformers::FoldSections < Snaptoken::DiffTransformers::BaseTransformer
2
- def transform(diff)
3
- sections = @options[:section_types].map { [] }
4
-
5
- cur_sections = @options[:section_types].map { nil }
6
- diff.lines.each.with_index do |line, idx|
7
- @options[:section_types].each.with_index do |section_type, level|
8
- if line.source =~ Regexp.new(section_type[:start])
9
- if !section_type[:end] && cur_sections[level]
10
- cur_sections[level].end_line = idx - 1
11
- if @options[:unfold_before_new_section]
12
- cur_sections[level].dirty! if [:added, :removed].include? line.type
13
- end
14
- sections[level] << cur_sections[level]
15
- end
16
-
17
- cur_sections[level] = Section.new(level, idx)
18
-
19
- if [:added, :removed].include? line.type
20
- cur_sections[level].dirty!
21
- end
22
- elsif section_type[:end] && line.source =~ Regexp.new(section_type[:end])
23
- if [:added, :removed].include? line.type
24
- cur_sections[level].dirty!
25
- end
26
-
27
- cur_sections[level].end_line = idx
28
- sections[level] << cur_sections[level]
29
- cur_sections[level] = nil
30
- elsif cur_sections[level]
31
- if [:added, :removed].include? line.type
32
- cur_sections[level].dirty!
33
- end
34
- end
35
- end
36
- end
37
- cur_sections.each.with_index do |section, level|
38
- unless section.nil?
39
- section.end_line = diff.lines.length - 1
40
- sections[level] << section
41
- end
42
- end
43
-
44
- new_diff = diff.clone
45
- sections.each.with_index do |level_sections, level|
46
- level_sections.each do |section|
47
- if !section.dirty? && !new_diff.lines[section.to_range].any?(&:nil?)
48
- start_line = new_diff.lines[section.start_line]
49
- end_line = new_diff.lines[section.end_line]
50
-
51
- summary_lines = [start_line]
52
- summary_lines << end_line if @options[:section_types][level][:end]
53
- summary = summary_lines.map(&:source).join(" … ")
54
-
55
- line_numbers = [start_line.line_number, end_line.line_number]
56
-
57
- folded_line = Snaptoken::DiffLine.new(:folded, summary, line_numbers)
58
-
59
- section.to_range.each do |idx|
60
- new_diff.lines[idx] = nil
61
- end
62
-
63
- new_diff.lines[section.start_line] = folded_line
64
- end
65
- end
66
- end
67
- new_diff.lines.compact!
68
- new_diff
69
- end
70
-
71
- class Section
72
- attr_accessor :level, :start_line, :end_line, :dirty
73
-
74
- def initialize(level, start_line, end_line = nil, dirty = false)
75
- @level, @start_line, @end_line, @dirty = level, start_line, end_line, dirty
76
- end
77
-
78
- def to_range
79
- start_line..end_line
80
- end
81
-
82
- def dirty?; @dirty; end
83
- def dirty!; @dirty = true; end
84
- end
85
- end
@@ -1,28 +0,0 @@
1
- class Snaptoken::DiffTransformers::OmitAdjacentRemovals < Snaptoken::DiffTransformers::BaseTransformer
2
- def transform(diff)
3
- new_diff = diff.clone
4
-
5
- removed_lines = []
6
- saw_added_line = false
7
- new_diff.lines.each.with_index do |line, idx|
8
- case line.type
9
- when :unchanged, :folded
10
- if saw_added_line
11
- removed_lines.each do |removed_idx|
12
- new_diff.lines[removed_idx] = nil
13
- end
14
- end
15
-
16
- removed_lines = []
17
- saw_added_line = false
18
- when :added
19
- saw_added_line = true
20
- when :removed
21
- removed_lines << idx
22
- end
23
- end
24
-
25
- new_diff.lines.compact!
26
- new_diff
27
- end
28
- end
@@ -1,21 +0,0 @@
1
- class Snaptoken::DiffTransformers::TrimBlankLines < Snaptoken::DiffTransformers::BaseTransformer
2
- def transform(diff)
3
- new_diff = diff.clone_empty
4
- diff.lines.each.with_index do |line, idx|
5
- line = line.clone
6
- if line.blank? && [:added, :removed].include?(line.type)
7
- prev_line = idx > 0 ? diff.lines[idx - 1] : nil
8
- next_line = idx < diff.lines.length - 1 ? diff.lines[idx + 1] : nil
9
-
10
- prev_changed = prev_line && [:added, :removed].include?(prev_line.type)
11
- next_changed = next_line && [:added, :removed].include?(next_line.type)
12
-
13
- if !prev_changed || !next_changed
14
- line.type = :unchanged
15
- end
16
- end
17
- new_diff.lines << line
18
- end
19
- new_diff
20
- end
21
- end
@@ -1,18 +0,0 @@
1
- module Snaptoken::Markdown
2
- class HTMLRouge < Redcarpet::Render::HTML
3
- include Rouge::Plugins::Redcarpet
4
- end
5
-
6
- HTML_RENDERER = HTMLRouge.new(with_toc_data: true)
7
- MARKDOWN_RENDERER = Redcarpet::Markdown.new(HTML_RENDERER, fenced_code_blocks: true)
8
-
9
- def self.render(source)
10
- html = MARKDOWN_RENDERER.render(source)
11
- html = Redcarpet::Render::SmartyPants.render(html)
12
- html.gsub!(/<\/code>&lsquo;/) { "</code>&rsquo;" }
13
- html.gsub!(/^\s*<h([23456]) id="([^"]+)">(.+)<\/h\d>$/) {
14
- "<h#{$1} id=\"#{$2}\"><a href=\"##{$2}\">#{$3}</a></h#{$1}>"
15
- }
16
- html
17
- end
18
- end
@@ -1,64 +0,0 @@
1
- class Snaptoken::Page
2
- attr_accessor :filename, :steps, :footer_text
3
-
4
- def initialize(filename = "tutorial")
5
- @filename = filename
6
- @steps = []
7
- @footer_text = nil
8
- end
9
-
10
- def <<(step)
11
- @steps << step
12
- self
13
- end
14
-
15
- def empty?
16
- @steps.empty?
17
- end
18
-
19
- def title
20
- first_line = @steps.first ? @steps.first.text.lines.first : (@footer_text ? @footer_text.lines.first : nil)
21
- if first_line && first_line.start_with?("# ")
22
- first_line[2..-1].strip
23
- end
24
- end
25
-
26
- def to_html(tutorial, offline)
27
- content = ""
28
- @steps.each do |step|
29
- if !step.text.strip.empty?
30
- html = Snaptoken::Markdown.render(step.text)
31
- html.gsub!(/<p>{{step (\d+)}}<\/p>/) do
32
- step = tutorial.step($1.to_i)
33
- step.syntax_highlight!
34
- step.to_html(tutorial, offline)
35
- end
36
- content << html
37
- end
38
-
39
- step.syntax_highlight!
40
- content << step.to_html(tutorial, offline)
41
- end
42
- if @footer_text
43
- # TODO: DRY this up. Please.
44
- html = Snaptoken::Markdown.render(@footer_text)
45
- html.gsub!(/<p>{{step (\d+)}}<\/p>/) do
46
- step = tutorial.step($1.to_i)
47
- step.syntax_highlight!
48
- step.to_html(tutorial, offline)
49
- end
50
- content << html
51
- end
52
-
53
- page_number = tutorial.pages.index(self) + 1
54
-
55
- Snaptoken::Template.new(tutorial.page_template, tutorial,
56
- offline: offline,
57
- page_title: title,
58
- content: content,
59
- page_number: page_number,
60
- prev_page: page_number > 1 ? tutorial.pages[page_number - 2] : nil,
61
- next_page: page_number < tutorial.pages.length ? tutorial.pages[page_number] : nil
62
- ).render_template
63
- end
64
- end
@@ -1,8 +0,0 @@
1
- module Snaptoken::Representations
2
- end
3
-
4
- require 'snaptoken/representations/base_representation'
5
-
6
- require 'snaptoken/representations/git'
7
- require 'snaptoken/representations/litdiff'
8
-
@@ -1,38 +0,0 @@
1
- class Snaptoken::Representations::BaseRepresentation
2
- def initialize(tutorial)
3
- @tutorial = tutorial
4
- end
5
-
6
- # Should save @tutorial to disk.
7
- def save!(options = {})
8
- raise NotImplementedError
9
- end
10
-
11
- # Should load @tutorial (in place) from disk, and return it.
12
- def load!(options = {})
13
- raise NotImplementedError
14
- end
15
-
16
- # Returns true if this representation has been modified by the user since the
17
- # last sync.
18
- def modified?
19
- synced_at = @tutorial.last_synced_at
20
- repr_modified_at = modified_at
21
- return false if synced_at.nil? or repr_modified_at.nil?
22
-
23
- repr_modified_at > synced_at
24
- end
25
-
26
- # Returns true if this representation currently exists on disk.
27
- def exists?
28
- !modified_at.nil?
29
- end
30
-
31
- private
32
-
33
- # Should return the Time the representation on disk was last modified, or nil
34
- # if the representation doesn't exist.
35
- def modified_at
36
- raise NotImplementedError
37
- end
38
- end
@@ -1,262 +0,0 @@
1
- class Snaptoken::Representations::Git < Snaptoken::Representations::BaseRepresentation
2
- def save!(options = {})
3
- FileUtils.rm_rf(repo_path)
4
- FileUtils.mkdir_p(repo_path)
5
-
6
- FileUtils.cd(repo_path) do
7
- repo = Rugged::Repository.init_at(".")
8
-
9
- step_num = 1
10
- @tutorial.pages.each do |page|
11
- message = "~~~ #{page.filename}"
12
- message << "\n\n#{page.footer_text}" if page.footer_text
13
- add_commit(repo, nil, message, step_num)
14
- page.steps.each do |step|
15
- message = "#{step.summary}\n\n#{step.text}".strip
16
- add_commit(repo, step.to_patch, message, step_num)
17
-
18
- yield step_num if block_given?
19
- step_num += 1
20
- end
21
- end
22
-
23
- #if options[:extra_path]
24
- # FileUtils.cp_r(File.join(options[:extra_path], "."), ".")
25
- # add_commit(repo, nil, "-", step_num, counter)
26
- #end
27
-
28
- repo.checkout_head(strategy: :force)
29
- end
30
- end
31
-
32
- # Options:
33
- # full_diffs: If true, diffs contain the entire file in one hunk instead of
34
- # multiple contextual hunks.
35
- # diffs_ignore_whitespace: If true, diffs don't show changes to lines when
36
- # only the amount of whitespace is changed.
37
- def load!(options = {})
38
- git_diff_options = {}
39
- git_diff_options[:context_lines] = 100_000 if options[:full_diffs]
40
- git_diff_options[:ignore_whitespace_change] = true if options[:diffs_ignore_whitespace]
41
-
42
- page = nil
43
- @tutorial.clear
44
- each_step(git_diff_options) do |step_num, commit, summary, text, patches|
45
- if patches.empty?
46
- if summary =~ /^~~~ (.+)$/
47
- @tutorial << page unless page.nil?
48
-
49
- page = Snaptoken::Page.new($1)
50
- page.footer_text = text unless text.empty?
51
- else
52
- puts "Warning: ignoring empty commit."
53
- end
54
- else
55
- patch = patches.map(&:to_s).join("\n")
56
- step_diffs = Snaptoken::Diff.parse(patch)
57
-
58
- page ||= Snaptoken::Page.new
59
- page << Snaptoken::Step.new(step_num, summary, text, step_diffs)
60
-
61
- yield step_num if block_given?
62
- end
63
- end
64
- @tutorial << page unless page.nil?
65
- @tutorial
66
- end
67
-
68
- def copy_repo_to_step!
69
- FileUtils.mkdir_p(step_path)
70
- FileUtils.rm_rf(File.join(step_path, "."), secure: true)
71
- FileUtils.cd(repo_path) do
72
- files = Dir.glob("*", File::FNM_DOTMATCH) - [".", "..", ".git"]
73
- files.each do |f|
74
- FileUtils.cp_r(f, File.join(step_path, f))
75
- end
76
- end
77
- end
78
-
79
- def copy_step_to_repo!
80
- FileUtils.mv(
81
- File.join(repo_path, ".git"),
82
- File.join(repo_path, "../.gittemp")
83
- )
84
- FileUtils.rm_rf(File.join(repo_path, "."), secure: true)
85
- FileUtils.mv(
86
- File.join(repo_path, "../.gittemp"),
87
- File.join(repo_path, ".git")
88
- )
89
- FileUtils.cd(step_path) do
90
- files = Dir.glob("*", File::FNM_DOTMATCH) - [".", ".."]
91
- files.each do |f|
92
- FileUtils.cp_r(f, File.join(repo_path, f))
93
- end
94
- end
95
- end
96
-
97
- def repo_path
98
- File.join(@tutorial.config[:path], ".leg/repo")
99
- end
100
-
101
- def repo
102
- @repo ||= Rugged::Repository.new(repo_path)
103
- end
104
-
105
- def each_commit(options = {})
106
- walker = Rugged::Walker.new(repo)
107
- walker.sorting(Rugged::SORT_TOPO | Rugged::SORT_REVERSE)
108
-
109
- master_commit = repo.branches["master"].target
110
- walker.push(master_commit)
111
-
112
- return [] if master_commit.oid == options[:after]
113
- walker.hide(options[:after]) if options[:after]
114
-
115
- return walker.to_a if not block_given?
116
-
117
- walker.each do |commit|
118
- yield commit
119
- end
120
- end
121
-
122
- alias_method :commits, :each_commit
123
-
124
- def each_step(git_diff_options = {})
125
- empty_tree = Rugged::Tree.empty(repo)
126
- step_num = 1
127
- each_commit do |commit|
128
- commit_message = commit.message.strip
129
- summary = commit_message.lines.first.strip
130
- text = (commit_message.lines[2..-1] || []).join.strip
131
- next if commit_message == "-"
132
- commit_message = "" if commit_message == "~"
133
- last_commit = commit.parents.first
134
- diff = (last_commit || empty_tree).diff(commit, git_diff_options)
135
- patches = diff.each_patch.to_a
136
-
137
- if patches.empty?
138
- yield nil, commit, summary, text, patches
139
- else
140
- yield step_num, commit, summary, text, patches
141
- step_num += 1
142
- end
143
- end
144
- end
145
-
146
- def commit!(options = {})
147
- copy_step_to_repo!
148
- remaining_commits = commits(after: repo.head.target).map(&:oid)
149
- FileUtils.cd(repo_path) do
150
- `git add -A`
151
- `git commit #{'--amend' if options[:amend]} -m"TODO: let user specify commit message"`
152
- end
153
- rebase!(remaining_commits)
154
- end
155
-
156
- def resolve!
157
- copy_step_to_repo!
158
- FileUtils.cd(repo_path) do
159
- `git add -A`
160
- `git -c core.editor=true cherry-pick --allow-empty --allow-empty-message --keep-redundant-commits --continue`
161
- end
162
- rebase!(load_remaining_commits)
163
- end
164
-
165
- def rebase!(remaining_commits)
166
- FileUtils.cd(repo_path) do
167
- remaining_commits.each.with_index do |commit, commit_idx|
168
- `git cherry-pick --allow-empty --allow-empty-message --keep-redundant-commits #{commit}`
169
-
170
- if not $?.success?
171
- copy_repo_to_step!
172
- save_remaining_commits(remaining_commits[(commit_idx+1)..-1])
173
- return false
174
- end
175
- end
176
- end
177
-
178
- save_remaining_commits(nil)
179
-
180
- repo.references.update(repo.branches["master"], repo.head.target_id)
181
- repo.head = "refs/heads/master"
182
-
183
- true
184
- end
185
-
186
- private
187
-
188
- def step_path
189
- File.join(@tutorial.config[:path], "step")
190
- end
191
-
192
- def remaining_commits_path
193
- File.join(@tutorial.config[:path], ".leg/remaining_commits")
194
- end
195
-
196
- def modified_at
197
- if File.exist? repo_path
198
- repo = Rugged::Repository.new(repo_path)
199
- if master = repo.branches.find { |b| b.name == "master" }
200
- master.target.time
201
- end
202
- end
203
- end
204
-
205
- def load_remaining_commits
206
- if File.exist?(remaining_commits_path)
207
- File.readlines(remaining_commits_path).map(&:strip).reject(&:empty?)
208
- else
209
- []
210
- end
211
- end
212
-
213
- def save_remaining_commits(remaining_commits)
214
- if remaining_commits && !remaining_commits.empty?
215
- File.write(remaining_commits_path, remaining_commits.join("\n"))
216
- else
217
- FileUtils.rm_f(remaining_commits_path)
218
- end
219
- end
220
-
221
- def add_commit(repo, diff, message, step_num)
222
- message ||= "~"
223
- message.strip!
224
- message = "~" if message.empty?
225
-
226
- if diff
227
- stdin = IO.popen("git apply -", "w")
228
- stdin.write diff
229
- stdin.close
230
- end
231
-
232
- index = repo.index
233
- index.read_tree(repo.head.target.tree) unless repo.empty?
234
-
235
- Dir["**/*"].each do |path|
236
- unless File.directory?(path)
237
- oid = repo.write(File.read(path), :blob)
238
- index.add(path: path, oid: oid, mode: 0100644)
239
- end
240
- end
241
-
242
- options = {}
243
- options[:tree] = index.write_tree(repo)
244
- if @tutorial.config[:repo_author_name]
245
- options[:author] = {
246
- name: @tutorial.config[:repo_author_name],
247
- email: @tutorial.config[:repo_author_email],
248
- time: Time.now
249
- }
250
- options[:committer] = options[:author]
251
- end
252
- options[:message] = message
253
- options[:parents] = repo.empty? ? [] : [repo.head.target]
254
- options[:update_ref] = "HEAD"
255
-
256
- commit_oid = Rugged::Commit.create(repo, options)
257
-
258
- if diff
259
- repo.references.create("refs/tags/step-#{step_num}", commit_oid)
260
- end
261
- end
262
- end