porrima 0.1.0 → 0.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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +133 -52
- data/lib/porrima/merge.rb +116 -11
- data/lib/porrima/version.rb +1 -1
- data/sig/porrima.rbs +14 -0
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 12e94d3fff8b491f17f5cb13beb41d396496816c54995c16be69b3aebdba875f
|
|
4
|
+
data.tar.gz: df24fab43b8358f2fcc522b548a1ead14ef53faf365a6601d0bc10c3a798aeed
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 24a68e804a09990a553b353e9ca2c547f64ca72cb382a121212ee1222f44b75d17b0ed07ca499a4200539279d245484723e602b43a3bb1972c51cbd86251b81c
|
|
7
|
+
data.tar.gz: b61f20f0ea9d25c231e30b1efd01a91152f7e3e76bd69edd3dec00c634c27123fcb15c9d2e4c66a33f35a2207d0b0c72d800cc2c605578ca42b15823a975824c
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0 — 2026-09-15
|
|
4
|
+
|
|
5
|
+
- Add zero-based merge output regions for conflict marker blocks.
|
|
6
|
+
- Add immutable single and bulk conflict resolution with custom replacement text.
|
|
7
|
+
- Add word-level inline refinement for conflict alternatives.
|
|
8
|
+
|
|
3
9
|
## 0.1.0 — 2026-09-12
|
|
4
10
|
|
|
5
11
|
- Initial release.
|
data/README.md
CHANGED
|
@@ -1,18 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
<h1 align="center">Porrima</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>Dependency-free line, word, and three-way diff, exact patching, and structured merge for Ruby.</strong>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://rubygems.org/gems/porrima"><img src="https://img.shields.io/gem/v/porrima.svg" alt="Gem version"></a>
|
|
9
|
+
<a href="https://github.com/noxdea/porrima/actions/workflows/main.yml"><img src="https://github.com/noxdea/porrima/actions/workflows/main.yml/badge.svg" alt="CI status"></a>
|
|
10
|
+
<a href="porrima.gemspec"><img src="https://img.shields.io/badge/CRuby-%3E%3D%203.1-cc342d.svg" alt="CRuby 3.1 or newer"></a>
|
|
11
|
+
<a href="LICENSE.txt"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT license"></a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<p align="center">
|
|
15
|
+
<a href="https://noxdea.github.io/porrima/">Website</a> ·
|
|
16
|
+
<a href="#features">Features</a> ·
|
|
17
|
+
<a href="#installation">Installation</a> ·
|
|
18
|
+
<a href="#quick-start">Quick start</a> ·
|
|
19
|
+
<a href="#core-api">Core API</a> ·
|
|
20
|
+
<a href="#cli">CLI</a>
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
Porrima turns two or three texts into structured edits, hunks, patches, and
|
|
26
|
+
merge conflicts. Its core performs no I/O, knows nothing about Git, and leaves
|
|
27
|
+
color, width, truncation, caching, and other display policy to the caller.
|
|
28
|
+
|
|
29
|
+
## Features
|
|
30
|
+
|
|
31
|
+
- Linear-space Myers diff for lines and inline word or character refinement
|
|
32
|
+
- Context hunks, change statistics, gutter marks, and paired rows
|
|
33
|
+
- Unified diff output with strict patch parsing, application, and reversal
|
|
34
|
+
- Three-way merge with structured conflicts, output regions, and immutable resolution
|
|
35
|
+
- CLI output as unified text or JSON
|
|
36
|
+
- No runtime dependencies
|
|
16
37
|
|
|
17
38
|
## Installation
|
|
18
39
|
|
|
@@ -20,43 +41,96 @@ files to the library's interoperable formats.
|
|
|
20
41
|
gem install porrima
|
|
21
42
|
```
|
|
22
43
|
|
|
44
|
+
Or add `gem "porrima"` to your Gemfile. Porrima requires CRuby 3.1 or newer.
|
|
45
|
+
|
|
23
46
|
## Quick start
|
|
24
47
|
|
|
25
48
|
```ruby
|
|
26
49
|
require "porrima"
|
|
27
50
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
51
|
+
before = "one\ntwo\n"
|
|
52
|
+
after = "one\nchanged\n"
|
|
53
|
+
diff = Porrima.diff(before, after, context: 1)
|
|
54
|
+
|
|
55
|
+
diff.stat.to_h
|
|
56
|
+
# => { insertions: 1, deletions: 1, hunks: 1 }
|
|
57
|
+
|
|
58
|
+
puts diff.to_unified(old_name: "a/example", new_name: "b/example")
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Core API
|
|
62
|
+
|
|
63
|
+
| API | Result |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| `Porrima.diff(before, after)` | Lazy `Diff` snapshot with every result view |
|
|
66
|
+
| `Porrima.edits(before, after)` | Ordered equal, deleted, and inserted lines |
|
|
67
|
+
| `Porrima.hunks(before, after)` | Context-aware change groups |
|
|
68
|
+
| `Porrima.unified(before, after)` | Unified diff text |
|
|
69
|
+
| `Porrima.apply(text, hunk)` | Text with one exact hunk applied |
|
|
70
|
+
| `Porrima.revert(text, hunk)` | Text with one exact hunk reversed |
|
|
71
|
+
| `Porrima::Inline.refine(before, after)` | Word- or character-level spans |
|
|
72
|
+
| `Porrima::Patch.parse(text)` | Parsed unified file diffs |
|
|
73
|
+
| `Porrima::Merge.three_way(...)` | Structured three-way merge result |
|
|
74
|
+
|
|
75
|
+
### Diff result
|
|
76
|
+
|
|
77
|
+
| View | Contains |
|
|
78
|
+
| --- | --- |
|
|
79
|
+
| `edits` | Equal, deleted, or inserted lines with old and new positions |
|
|
80
|
+
| `hunks` | Context-aware groups with exact old and new text |
|
|
81
|
+
| `stat` | Insertion, deletion, and hunk counts |
|
|
82
|
+
| `marks` | Added, modified, or removed ranges on the new side |
|
|
83
|
+
| `rows` | Old and new lines paired for side-by-side display |
|
|
84
|
+
|
|
85
|
+
Use `hunk_at(new_line:)` or `mark_at(new_line:)` for position lookup,
|
|
86
|
+
`to_unified` for interoperable text, and `to_h` for serialization.
|
|
87
|
+
|
|
88
|
+
`Diff` snapshots its inputs and lazily memoizes these collections. Finish the
|
|
89
|
+
fields needed by another thread on the producing thread before sharing it.
|
|
34
90
|
|
|
91
|
+
### Inline diff
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
35
94
|
old_spans, new_spans = Porrima::Inline.refine("hello old", "hello new")
|
|
36
|
-
|
|
37
|
-
patch.apply("one\ntwo\n")
|
|
95
|
+
```
|
|
38
96
|
|
|
39
|
-
|
|
40
|
-
|
|
97
|
+
Pass `granularity: :char` to compare grapheme clusters instead of words.
|
|
98
|
+
|
|
99
|
+
### Patch
|
|
100
|
+
|
|
101
|
+
```ruby
|
|
102
|
+
file = Porrima::Patch.parse(diff.to_unified).first
|
|
103
|
+
file.applies?(before) # => true
|
|
104
|
+
file.apply(before) # => "one\nchanged\n"
|
|
105
|
+
file.revert(after) # => "one\ntwo\n"
|
|
41
106
|
```
|
|
42
107
|
|
|
43
|
-
|
|
44
|
-
as lower-level entry points. `Porrima::Budget` can replace an oversized input
|
|
45
|
-
as one block or raise `Porrima::BudgetExceeded`.
|
|
108
|
+
Patch application is exact: stale or malformed input raises a Porrima error.
|
|
46
109
|
|
|
47
|
-
|
|
110
|
+
### Three-way merge
|
|
48
111
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
112
|
+
```ruby
|
|
113
|
+
merge = Porrima::Merge.three_way(
|
|
114
|
+
base: "old\n",
|
|
115
|
+
ours: "ours\n",
|
|
116
|
+
theirs: "theirs\n"
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
merge.clean?
|
|
120
|
+
merge.conflicts
|
|
121
|
+
merge.regions # zero-based locations in merge-marker output
|
|
122
|
+
Porrima::Merge.to_text(merge, style: :diff3)
|
|
56
123
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
124
|
+
resolved = Porrima::Merge.resolve(merge, 0, :ours)
|
|
125
|
+
Porrima::Merge.to_resolved_text(resolved) # => "ours\n"
|
|
126
|
+
Porrima::Merge.conflict_inline(merge.conflicts.first)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`resolve` accepts `:ours`, `:theirs`, `:base`, `:ours_then_theirs`,
|
|
130
|
+
`:theirs_then_ours`, a replacement string, or an array of replacement strings.
|
|
131
|
+
It returns a new result and leaves the source result unchanged. Use `resolve_all`
|
|
132
|
+
to apply one choice to every conflict. `to_resolved_text` rejects results that
|
|
133
|
+
still contain a conflict.
|
|
60
134
|
|
|
61
135
|
## CLI
|
|
62
136
|
|
|
@@ -68,14 +142,24 @@ porrima apply [options] PATCH [FILE]
|
|
|
68
142
|
|
|
69
143
|
Diff supports unified output, `--json`, `--quiet`, and `--max-bytes`. Merge
|
|
70
144
|
supports structured JSON or `diff3`/`merge` markers. Apply supports
|
|
71
|
-
`--reverse` and validation-only `--check`.
|
|
72
|
-
diff/conflict, 1 for a diff/conflict, and 2 for an error.
|
|
145
|
+
`--reverse` and validation-only `--check`.
|
|
73
146
|
|
|
74
|
-
|
|
147
|
+
Exit status is 0 for no diff or conflict, 1 for a diff or conflict, and 2 for
|
|
148
|
+
an error.
|
|
75
149
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
150
|
+
## Compatibility and limits
|
|
151
|
+
|
|
152
|
+
- Line edits, hunks, unified output, and revert behavior are byte-compatible
|
|
153
|
+
with the original Canopus diff engine.
|
|
154
|
+
- Public struct field names and order are part of the 0.1 contract.
|
|
155
|
+
- Comparison uses `String#==`; callers own encoding normalization.
|
|
156
|
+
- Patch application intentionally has no fuzz matching.
|
|
157
|
+
- Inline refinement treats over 2,000 combined tokens as one replacement.
|
|
158
|
+
- Merge region positions are zero-based and cover the complete conflict marker
|
|
159
|
+
block produced by `to_text(style: :merge)`.
|
|
160
|
+
- `Porrima::Budget` can replace an oversized input as one block or raise
|
|
161
|
+
`Porrima::BudgetExceeded`.
|
|
162
|
+
- During 0.x releases, minor versions may contain breaking changes.
|
|
79
163
|
|
|
80
164
|
## Development
|
|
81
165
|
|
|
@@ -88,14 +172,11 @@ bundle exec rake bench:assert
|
|
|
88
172
|
gem build --strict porrima.gemspec
|
|
89
173
|
```
|
|
90
174
|
|
|
91
|
-
##
|
|
175
|
+
## Contributing
|
|
92
176
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
- Inline refinement treats over 2,000 combined tokens as a whole-text replacement.
|
|
96
|
-
- `Diff` memoization is not synchronized; complete it before cross-thread use.
|
|
97
|
-
- During 0.x releases, minor versions may contain breaking changes.
|
|
177
|
+
Bug reports and pull requests are welcome on
|
|
178
|
+
[GitHub](https://github.com/noxdea/porrima).
|
|
98
179
|
|
|
99
180
|
## License
|
|
100
181
|
|
|
101
|
-
Porrima is
|
|
182
|
+
Porrima is available under the [MIT License](LICENSE.txt).
|
data/lib/porrima/merge.rb
CHANGED
|
@@ -4,17 +4,56 @@ module Porrima
|
|
|
4
4
|
module Merge
|
|
5
5
|
Change = Struct.new(:start, :finish, :replacement, :side, keyword_init: true)
|
|
6
6
|
Conflict = Struct.new(:base_start, :base_count, :base, :ours, :theirs, keyword_init: true)
|
|
7
|
+
Region = Struct.new(:conflict, :output_start, :output_count, :index, keyword_init: true)
|
|
8
|
+
RESOLUTION_CHOICES = %i[ours theirs base ours_then_theirs theirs_then_ours].freeze
|
|
9
|
+
private_constant :RESOLUTION_CHOICES
|
|
7
10
|
|
|
8
11
|
class Result
|
|
9
12
|
attr_reader :sections, :conflicts
|
|
10
13
|
|
|
11
14
|
def initialize(sections)
|
|
12
|
-
|
|
13
|
-
@
|
|
15
|
+
raise ArgumentError, "sections must be an array" unless sections.is_a?(Array)
|
|
16
|
+
@sections = sections.map { |section| snapshot(section) }.freeze
|
|
17
|
+
@conflicts = @sections.grep(Conflict).freeze
|
|
14
18
|
freeze
|
|
15
19
|
end
|
|
16
20
|
|
|
17
21
|
def clean? = conflicts.empty?
|
|
22
|
+
def resolved? = conflicts.empty?
|
|
23
|
+
|
|
24
|
+
def regions
|
|
25
|
+
output_line = conflict_index = 0
|
|
26
|
+
sections.each_with_object([]) do |section, regions|
|
|
27
|
+
unless section.is_a?(Conflict)
|
|
28
|
+
output_line += section.count("\n")
|
|
29
|
+
next
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
marked = +""
|
|
33
|
+
Merge.send(:append_conflict_text, marked, section, :merge, ["ours", "base", "theirs"])
|
|
34
|
+
output_count = marked.count("\n")
|
|
35
|
+
regions << Region.new(conflict: section, output_start: output_line,
|
|
36
|
+
output_count: output_count, index: conflict_index).freeze
|
|
37
|
+
output_line += output_count
|
|
38
|
+
conflict_index += 1
|
|
39
|
+
end.freeze
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def snapshot(section)
|
|
45
|
+
return section.dup.freeze if section.is_a?(String)
|
|
46
|
+
raise ArgumentError, "sections must contain strings or conflicts" unless section.is_a?(Conflict)
|
|
47
|
+
unless section.base_start.is_a?(Integer) && section.base_start >= 0 &&
|
|
48
|
+
section.base_count.is_a?(Integer) && section.base_count >= 0 &&
|
|
49
|
+
[section.base, section.ours, section.theirs].all?(String)
|
|
50
|
+
raise ArgumentError, "invalid conflict"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
Conflict.new(base_start: section.base_start, base_count: section.base_count,
|
|
54
|
+
base: section.base.dup.freeze, ours: section.ours.dup.freeze,
|
|
55
|
+
theirs: section.theirs.dup.freeze).freeze
|
|
56
|
+
end
|
|
18
57
|
end
|
|
19
58
|
|
|
20
59
|
module_function
|
|
@@ -65,16 +104,38 @@ module Porrima
|
|
|
65
104
|
output << section
|
|
66
105
|
next
|
|
67
106
|
end
|
|
68
|
-
output
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
output << ">>>>>>> #{labels[2]}\n"
|
|
107
|
+
append_conflict_text(output, section, style, labels)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def resolve(result, index, choice)
|
|
112
|
+
validate_result(result)
|
|
113
|
+
unless index.is_a?(Integer) && index.between?(0, result.conflicts.length - 1)
|
|
114
|
+
raise ArgumentError, "index must identify a conflict"
|
|
77
115
|
end
|
|
116
|
+
validate_choice(choice)
|
|
117
|
+
conflict = result.conflicts[index]
|
|
118
|
+
Result.new(result.sections.map { |section| section.equal?(conflict) ? resolution_text(conflict, choice) : section })
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def resolve_all(result, choice)
|
|
122
|
+
validate_result(result)
|
|
123
|
+
validate_choice(choice)
|
|
124
|
+
Result.new(result.sections.map { |section| section.is_a?(Conflict) ? resolution_text(section, choice) : section })
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def to_resolved_text(result)
|
|
128
|
+
validate_result(result)
|
|
129
|
+
raise ArgumentError, "merge result has unresolved conflicts" unless result.resolved?
|
|
130
|
+
result.sections.join
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def conflict_inline(conflict)
|
|
134
|
+
unless conflict.is_a?(Conflict) && [conflict.ours, conflict.theirs].all?(String)
|
|
135
|
+
raise ArgumentError, "conflict must contain ours and theirs text"
|
|
136
|
+
end
|
|
137
|
+
ours, theirs = Inline.refine(conflict.ours, conflict.theirs)
|
|
138
|
+
{ours: ours, theirs: theirs}
|
|
78
139
|
end
|
|
79
140
|
|
|
80
141
|
def lines(text) = text.is_a?(String) ? text.lines : text
|
|
@@ -130,5 +191,49 @@ module Porrima
|
|
|
130
191
|
output << "\n" unless text.empty? || text.end_with?("\n")
|
|
131
192
|
end
|
|
132
193
|
private_class_method :append_marked_text
|
|
194
|
+
|
|
195
|
+
def append_conflict_text(output, conflict, style, labels)
|
|
196
|
+
output << "<<<<<<< #{labels[0]}\n"
|
|
197
|
+
append_marked_text(output, conflict.ours)
|
|
198
|
+
if style == :diff3
|
|
199
|
+
output << "||||||| #{labels[1]}\n"
|
|
200
|
+
append_marked_text(output, conflict.base)
|
|
201
|
+
end
|
|
202
|
+
output << "=======\n"
|
|
203
|
+
append_marked_text(output, conflict.theirs)
|
|
204
|
+
output << ">>>>>>> #{labels[2]}\n"
|
|
205
|
+
end
|
|
206
|
+
private_class_method :append_conflict_text
|
|
207
|
+
|
|
208
|
+
def validate_result(result)
|
|
209
|
+
raise ArgumentError, "result must be a Porrima::Merge::Result" unless result.is_a?(Result)
|
|
210
|
+
end
|
|
211
|
+
private_class_method :validate_result
|
|
212
|
+
|
|
213
|
+
def validate_choice(choice)
|
|
214
|
+
valid = RESOLUTION_CHOICES.include?(choice) || choice.is_a?(String) ||
|
|
215
|
+
(choice.is_a?(Array) && choice.all?(String))
|
|
216
|
+
raise ArgumentError, "invalid resolution choice" unless valid
|
|
217
|
+
end
|
|
218
|
+
private_class_method :validate_choice
|
|
219
|
+
|
|
220
|
+
def resolution_text(conflict, choice)
|
|
221
|
+
case choice
|
|
222
|
+
when :ours then conflict.ours
|
|
223
|
+
when :theirs then conflict.theirs
|
|
224
|
+
when :base then conflict.base
|
|
225
|
+
when :ours_then_theirs then join_alternatives(conflict.ours, conflict.theirs)
|
|
226
|
+
when :theirs_then_ours then join_alternatives(conflict.theirs, conflict.ours)
|
|
227
|
+
when Array then choice.join
|
|
228
|
+
else choice
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
private_class_method :resolution_text
|
|
232
|
+
|
|
233
|
+
def join_alternatives(first, second)
|
|
234
|
+
return first + second if first.empty? || second.empty? || first.end_with?("\n")
|
|
235
|
+
first + "\n" + second
|
|
236
|
+
end
|
|
237
|
+
private_class_method :join_alternatives
|
|
133
238
|
end
|
|
134
239
|
end
|
data/lib/porrima/version.rb
CHANGED
data/sig/porrima.rbs
CHANGED
|
@@ -2,6 +2,7 @@ module Porrima
|
|
|
2
2
|
VERSION: String
|
|
3
3
|
type lines = String | Array[String]
|
|
4
4
|
type kind = :equal | :delete | :insert
|
|
5
|
+
type merge_choice = :ours | :theirs | :base | :ours_then_theirs | :theirs_then_ours | String | Array[String]
|
|
5
6
|
|
|
6
7
|
class Error < StandardError
|
|
7
8
|
end
|
|
@@ -110,14 +111,27 @@ module Porrima
|
|
|
110
111
|
attr_accessor theirs: String
|
|
111
112
|
def self.new: (base_start: Integer, base_count: Integer, base: String, ours: String, theirs: String) -> instance
|
|
112
113
|
end
|
|
114
|
+
class Region < Struct[untyped]
|
|
115
|
+
attr_accessor conflict: Conflict
|
|
116
|
+
attr_accessor output_start: Integer
|
|
117
|
+
attr_accessor output_count: Integer
|
|
118
|
+
attr_accessor index: Integer
|
|
119
|
+
def self.new: (conflict: Conflict, output_start: Integer, output_count: Integer, index: Integer) -> instance
|
|
120
|
+
end
|
|
113
121
|
class Result
|
|
114
122
|
attr_reader sections: Array[String | Conflict]
|
|
115
123
|
attr_reader conflicts: Array[Conflict]
|
|
116
124
|
def initialize: (Array[String | Conflict]) -> void
|
|
117
125
|
def clean?: () -> bool
|
|
126
|
+
def resolved?: () -> bool
|
|
127
|
+
def regions: () -> Array[Region]
|
|
118
128
|
end
|
|
119
129
|
def self.three_way: (base: String, ours: String, theirs: String) -> Result
|
|
120
130
|
def self.to_text: (Result, ?style: (:diff3 | :merge), ?labels: Array[String]) -> String
|
|
131
|
+
def self.resolve: (Result, Integer, merge_choice) -> Result
|
|
132
|
+
def self.resolve_all: (Result, merge_choice) -> Result
|
|
133
|
+
def self.to_resolved_text: (Result) -> String
|
|
134
|
+
def self.conflict_inline: (Conflict) -> { ours: Array[Span], theirs: Array[Span] }
|
|
121
135
|
end
|
|
122
136
|
|
|
123
137
|
def self.diff: (lines, lines, ?context: Integer, ?budget: Budget?) -> Diff
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: porrima
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yudai Takada
|
|
@@ -10,7 +10,8 @@ cert_chain: []
|
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies: []
|
|
12
12
|
description: Linear-space Myers diff with context hunks, gutter marks, paired rows,
|
|
13
|
-
unified output, strict patch application, and three-way merge. No I/O,
|
|
13
|
+
unified output, strict patch application, and resolvable three-way merge. No I/O,
|
|
14
|
+
no dependencies.
|
|
14
15
|
email:
|
|
15
16
|
- t.yudai92@gmail.com
|
|
16
17
|
executables:
|
|
@@ -58,7 +59,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
58
59
|
- !ruby/object:Gem::Version
|
|
59
60
|
version: '0'
|
|
60
61
|
requirements: []
|
|
61
|
-
rubygems_version:
|
|
62
|
+
rubygems_version: 3.6.9
|
|
62
63
|
specification_version: 4
|
|
63
64
|
summary: Line, word, and three-way diff, patch, and merge in pure Ruby
|
|
64
65
|
test_files: []
|