tractive 1.0.10 → 1.0.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/README.adoc +8 -0
- data/exe/command_base.rb +2 -0
- data/exe/tractive +6 -0
- data/lib/tractive/attachment_exporter.rb +4 -3
- data/lib/tractive/main.rb +3 -0
- data/lib/tractive/migrator/converter/trac_to_github.rb +4 -3
- data/lib/tractive/migrator/converter/twf_to_markdown.rb +237 -38
- data/lib/tractive/migrator/wikis/migrate_from_db.rb +45 -5
- data/lib/tractive/utilities.rb +4 -0
- data/lib/tractive/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0db013dccdcc48d417706b5f52036b4c5801b4d81d6a835c09ee4b1afc6480db
|
4
|
+
data.tar.gz: 4603e9e32107e75a4e2f495dc4a93cbc4e810a65c2bee576721e7d58d4be78cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5cf948f6fd3aed7f3b67778e91e9d88e7e1f9586824e21c4a1a0a4a42b42a14eedac4df7d5bf7627e182741ccf35865e195c1990c18e008b352b43bee08d4f4a
|
7
|
+
data.tar.gz: f2b76c16fdf603a4d084df7a895f6ffdef16b4fc9297e6f039d9894e4b95a14a6d31ef090399983f46e68f4b904485df41102f3749926aef8adffee8e7d4011a
|
data/.rubocop.yml
CHANGED
@@ -18,6 +18,7 @@ Metrics/ClassLength:
|
|
18
18
|
|
19
19
|
Metrics/BlockLength:
|
20
20
|
Max: 500
|
21
|
+
IgnoredMethods: ['describe']
|
21
22
|
|
22
23
|
Style/Documentation:
|
23
24
|
Enabled: false
|
@@ -37,6 +38,9 @@ Metrics/MethodLength:
|
|
37
38
|
Metrics/ModuleLength:
|
38
39
|
Max: 150
|
39
40
|
|
41
|
+
Metrics/ParameterLists:
|
42
|
+
Max: 6
|
43
|
+
|
40
44
|
Security/Open:
|
41
45
|
Enabled: false
|
42
46
|
|
data/README.adoc
CHANGED
@@ -802,6 +802,14 @@ If attachment files are reachable via a URL we reference this here.
|
|
802
802
|
| Path to config file.
|
803
803
|
| String
|
804
804
|
|
805
|
+
| `-e`, `--wiki-extensions`
|
806
|
+
| Space separated list of extensions or filenames (if the file don't have an extension). This is required to convert file SVN source links to Github links. This is used to determine if a path belongs to a file or a directory.
|
807
|
+
| Array
|
808
|
+
|
809
|
+
| `-f`, `--source-folders`
|
810
|
+
| Space separated list of non standard folders in SVN that are used to find if a path is complete or partial.
|
811
|
+
| Array
|
812
|
+
|
805
813
|
|===
|
806
814
|
|
807
815
|
|
data/exe/command_base.rb
CHANGED
@@ -7,5 +7,7 @@ class CommandBase < Thor
|
|
7
7
|
desc: "Name of the logfile to output logs to."
|
8
8
|
class_option "config", type: :string, default: "tractive.config.yaml", banner: "<PATH>", aliases: "-c",
|
9
9
|
desc: "Set the configuration file"
|
10
|
+
class_option "git-token", type: :string,
|
11
|
+
desc: "The access token for Github actions."
|
10
12
|
class_option "verbose", type: :boolean, aliases: ["-v", "--verbose"], desc: "Verbose mode"
|
11
13
|
end
|
data/exe/tractive
CHANGED
@@ -58,6 +58,12 @@ class TractiveCommand < CommandBase
|
|
58
58
|
desc: "Full path of the Trac sqlite3 database export file"
|
59
59
|
method_option "repo-path", type: :string, aliases: ["-r"], banner: "/GIT/ROOT/DIR",
|
60
60
|
desc: "Full path to the root of the git-repository that is our destination"
|
61
|
+
method_option "home-page-name", type: :string, aliases: ["-h"], default: "WikiStart",
|
62
|
+
desc: "Name of the SVN wiki to map to the home page in Github wiki"
|
63
|
+
method_option "wiki-extensions", type: :array, aliases: ["-e"], default: [".py", "changelog", "expire-ids"],
|
64
|
+
desc: "Array of strings to determinte whether a given path is a file path or a directory in wiki"
|
65
|
+
method_option "source-folders", type: :array, aliases: ["-f"], default: ["personal", "attic", "sprint", "branch/hawk"],
|
66
|
+
desc: "Array of strings to figure out if a path is complete or partial"
|
61
67
|
def migrate_wikis
|
62
68
|
Tractive::Main.new(options).migrate_wikis
|
63
69
|
end
|
@@ -53,9 +53,10 @@ module Tractive
|
|
53
53
|
$logger.info "Saving attachments of ticket #{attachment.id}... "
|
54
54
|
FileUtils.mkdir_p "#{output_dir}/#{attachment.id}"
|
55
55
|
|
56
|
-
File.
|
57
|
-
|
58
|
-
|
56
|
+
File.binwrite(
|
57
|
+
"#{output_dir}/#{attachment.id}/#{attachment.filename}",
|
58
|
+
URI.open(uri_parser.escape("#{trac_url}/#{attachment.id}/#{attachment.filename}")).read
|
59
|
+
)
|
59
60
|
end
|
60
61
|
end
|
61
62
|
end
|
data/lib/tractive/main.rb
CHANGED
@@ -8,6 +8,9 @@ module Tractive
|
|
8
8
|
@opts = opts
|
9
9
|
@cfg = YAML.load_file(@opts[:config])
|
10
10
|
|
11
|
+
@cfg["github"] ||= {}
|
12
|
+
@cfg["github"]["token"] = @opts["git-token"]
|
13
|
+
|
11
14
|
Tractive::Utilities.setup_logger(output_stream: @opts[:logfile] || $stderr, verbose: @opts[:verbose])
|
12
15
|
@db = Tractive::Utilities.setup_db!(@opts["trac-database-path"] || @cfg["trac"]["database"])
|
13
16
|
rescue Sequel::DatabaseConnectionError, Sequel::AdapterNotFound, URI::InvalidURIError, Sequel::DatabaseError => e
|
@@ -33,7 +33,8 @@ module Migrator
|
|
33
33
|
@attachment_options,
|
34
34
|
@changeset_base_url,
|
35
35
|
@wiki_attachments_url,
|
36
|
-
@revmap_file_path
|
36
|
+
@revmap_file_path,
|
37
|
+
git_repo: @repo, home_page_name: args[:opts]["home-page-name"]
|
37
38
|
)
|
38
39
|
end
|
39
40
|
|
@@ -280,7 +281,7 @@ module Migrator
|
|
280
281
|
# text += "created the issue\n\n"
|
281
282
|
if body && !body.lstrip.empty?
|
282
283
|
# text += "\n___\n" if not append
|
283
|
-
text += @twf_to_markdown.convert(body)
|
284
|
+
text += @twf_to_markdown.convert(body, id: meta[:ticket])
|
284
285
|
end
|
285
286
|
|
286
287
|
when "comment"
|
@@ -294,7 +295,7 @@ module Migrator
|
|
294
295
|
end
|
295
296
|
|
296
297
|
text += "\n___\n" unless append
|
297
|
-
text += @twf_to_markdown.convert(body) if body
|
298
|
+
text += @twf_to_markdown.convert(body, id: meta[:ticket]) if body
|
298
299
|
|
299
300
|
when "attachment"
|
300
301
|
text += "_uploaded file "
|
@@ -1,27 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "cgi"
|
4
|
+
|
3
5
|
module Migrator
|
4
6
|
module Converter
|
5
7
|
# twf => Trac wiki format
|
6
8
|
class TwfToMarkdown
|
7
|
-
def initialize(base_url, attachment_options, changeset_base_url, wiki_attachments_url, revmap_file_path)
|
9
|
+
def initialize(base_url, attachment_options, changeset_base_url, wiki_attachments_url, revmap_file_path, options = {})
|
8
10
|
@base_url = base_url
|
9
11
|
@attach_url = attachment_options[:url]
|
10
12
|
@attach_hashed = attachment_options[:hashed]
|
11
13
|
@changeset_base_url = changeset_base_url
|
12
14
|
@wiki_attachments_url = wiki_attachments_url
|
13
15
|
@revmap = load_revmap_file(revmap_file_path)
|
16
|
+
|
17
|
+
@git_repo = options[:git_repo]
|
18
|
+
@home_page_name = options[:home_page_name]
|
19
|
+
@wiki_extensions = options[:wiki_extensions]
|
20
|
+
@source_folders = options[:source_folders]
|
14
21
|
end
|
15
22
|
|
16
|
-
def convert(str)
|
23
|
+
def convert(str, image_options = {})
|
24
|
+
# Fix 'Windows EOL' to 'Linux EOL'
|
25
|
+
str.gsub!("\r\n", "\n")
|
26
|
+
|
27
|
+
convert_tables(str)
|
17
28
|
convert_newlines(str)
|
29
|
+
convert_comments(str)
|
30
|
+
convert_html_snippets(str)
|
18
31
|
convert_code_snippets(str)
|
19
32
|
convert_headings(str)
|
20
|
-
convert_links(str)
|
33
|
+
convert_links(str, @git_repo)
|
21
34
|
convert_font_styles(str)
|
22
35
|
convert_changeset(str, @changeset_base_url)
|
23
|
-
convert_image(str, @base_url, @attach_url, @wiki_attachments_url)
|
36
|
+
convert_image(str, @base_url, @attach_url, @wiki_attachments_url, image_options)
|
24
37
|
convert_ticket(str, @base_url)
|
38
|
+
revert_intermediate_references(str)
|
25
39
|
|
26
40
|
str
|
27
41
|
end
|
@@ -46,18 +60,12 @@ module Migrator
|
|
46
60
|
revmap
|
47
61
|
end
|
48
62
|
|
49
|
-
# CommitTicketReference
|
50
|
-
def convert_ticket_reference(str)
|
51
|
-
str.gsub!(/\{\{\{\n(#!CommitTicketReference .+?)\}\}\}/m, '\1')
|
52
|
-
str.gsub!(/#!CommitTicketReference .+\n/, "")
|
53
|
-
end
|
54
|
-
|
55
63
|
# Ticket
|
56
64
|
def convert_ticket(str, base_url)
|
57
65
|
# replace a full ticket id with the github short refrence
|
58
66
|
if base_url
|
59
67
|
baseurlpattern = base_url.gsub("/", "\\/")
|
60
|
-
str.gsub!(%r{#{baseurlpattern}/(\d+)}
|
68
|
+
str.gsub!(%r{#{baseurlpattern}/(\d+)}, '#\1')
|
61
69
|
end
|
62
70
|
|
63
71
|
# Ticket
|
@@ -80,16 +88,35 @@ module Migrator
|
|
80
88
|
str.gsub!("\r\n", "\n")
|
81
89
|
end
|
82
90
|
|
91
|
+
# Comments
|
92
|
+
def convert_comments(str)
|
93
|
+
str.gsub!(/\{\{\{(?>((?!(?:}}}|{{{)).+?|\g<0>))*\}\}\}/m) do |str_match|
|
94
|
+
str_match.gsub(/\{\{\{\s*#!comment(\s*)(.*)\}\}\}/m, '<!--\1\2\1-->')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# HTML Snippets
|
99
|
+
def convert_html_snippets(str)
|
100
|
+
str.gsub!(/\{\{\{#!html(.*?)\}\}\}/m, '\1')
|
101
|
+
end
|
102
|
+
|
103
|
+
# CommitTicketReference
|
104
|
+
def convert_ticket_reference(str)
|
105
|
+
str.gsub!(/\{\{\{\n(#!CommitTicketReference .+?)\}\}\}/m, '\1')
|
106
|
+
str.gsub!(/#!CommitTicketReference .+\n/, "")
|
107
|
+
end
|
108
|
+
|
83
109
|
# Code
|
84
110
|
def convert_code_snippets(str)
|
85
111
|
str.gsub!(/\{\{\{([^\n]+?)\}\}\}/, '`\1`')
|
112
|
+
str.gsub!(/\{\{\{#!(.*?)\n(.+?)\}\}\}/m, "```\\1\n\\2\n```")
|
86
113
|
str.gsub!(/\{\{\{(.+?)\}\}\}/m, '```\1```')
|
87
114
|
str.gsub!(/(?<=```)#!/m, "")
|
88
115
|
end
|
89
116
|
|
90
117
|
# Changeset
|
91
118
|
def convert_changeset(str, changeset_base_url)
|
92
|
-
str.gsub!(%r{#{Regexp.quote(changeset_base_url)}/(\d+)/?}, '[changeset:\1]') if changeset_base_url
|
119
|
+
str.gsub!(%r{#{Regexp.quote(changeset_base_url)}/(\d+)/?}, '[changeset:\1]') if changeset_base_url && !changeset_base_url.empty?
|
93
120
|
str.gsub!(/\[changeset:"r(\d+)".*\]/, '[changeset:\1]')
|
94
121
|
str.gsub!(/\[changeset:r(\d+)\]/, '[changeset:\1]')
|
95
122
|
str.gsub!(/\br(\d+)\b/) { Tractive::Utilities.map_changeset(Regexp.last_match[1], @revmap, changeset_base_url) }
|
@@ -103,44 +130,216 @@ module Migrator
|
|
103
130
|
def convert_font_styles(str)
|
104
131
|
str.gsub!(/'''(.+?)'''/, '**\1**')
|
105
132
|
str.gsub!(/''(.+?)''/, '*\1*')
|
106
|
-
str.gsub!(%r{[^:]//(.+?[^:])//}, '
|
133
|
+
str.gsub!(%r{([^:])//(.+?[^:])//}, '\1_\2_')
|
134
|
+
end
|
135
|
+
|
136
|
+
# Tables
|
137
|
+
def convert_tables(str)
|
138
|
+
str.gsub!(/^( *\|\|[^\n]+\|\| *[^\n|]+$)+$/, '\1 ||')
|
139
|
+
|
140
|
+
str.gsub!(/(?:^( *\|\|[^\n]+\|\| *)\n?)+/) do |match_result|
|
141
|
+
rows = match_result.gsub("||", "|").split("\n")
|
142
|
+
rows.insert(1, "| #{"--- | " * (rows[0].split("|").size - 1)}".strip)
|
143
|
+
|
144
|
+
"#{rows.join("\n")}\n"
|
145
|
+
end
|
107
146
|
end
|
108
147
|
|
109
148
|
# Links
|
110
|
-
def convert_links(str)
|
111
|
-
str
|
149
|
+
def convert_links(str, git_repo)
|
150
|
+
convert_camel_case_links(str, git_repo)
|
151
|
+
convert_double_bracket_wiki_links(str, git_repo)
|
152
|
+
convert_single_bracket_wiki_links(str, git_repo)
|
153
|
+
|
154
|
+
str.gsub!(/(^!)\[(http[^\s\[\]]+)\s([^\[\]]+)\]/, '[\2](\1)')
|
112
155
|
str.gsub!(/!(([A-Z][a-z0-9]+){2,})/, '\1')
|
113
156
|
end
|
114
157
|
|
115
|
-
def
|
158
|
+
def convert_single_bracket_wiki_links(str, git_repo)
|
159
|
+
str.gsub!(/(!?)\[((?:wiki|source):)?([^\s\]]*) ?(.*?)\]/) do |match_result|
|
160
|
+
source = Regexp.last_match[2]
|
161
|
+
path = Regexp.last_match[3]
|
162
|
+
name = Regexp.last_match[4]
|
163
|
+
|
164
|
+
formatted_link(
|
165
|
+
match_result,
|
166
|
+
git_repo,
|
167
|
+
{ source: source, path: path, name: name }
|
168
|
+
)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def convert_double_bracket_wiki_links(str, git_repo)
|
173
|
+
str.gsub!(/(!?)\[\[((?:wiki|source):)?([^|\n]*)\|?(.*?)\]\]/) do |match_result|
|
174
|
+
source = Regexp.last_match[2]
|
175
|
+
path = Regexp.last_match[3]
|
176
|
+
name = Regexp.last_match[4]
|
177
|
+
|
178
|
+
formatted_link(
|
179
|
+
match_result,
|
180
|
+
git_repo,
|
181
|
+
{ source: source, path: path, name: name }
|
182
|
+
)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def formatted_link(unformatted_text, git_repo, url_options = {})
|
187
|
+
return unformatted_text.gsub("!", "{~") if unformatted_text.start_with?("!")
|
188
|
+
|
189
|
+
if url_options[:source] == "wiki:"
|
190
|
+
link, internal_link = url_options[:path].split("#")
|
191
|
+
link = "Home" if link == @home_page_name
|
192
|
+
internal_link = Tractive::Utilities.dasharize(internal_link) if internal_link
|
193
|
+
url_options[:name] = link if url_options[:name].empty?
|
194
|
+
"{{#{url_options[:name]}}}(https://github.com/#{git_repo}/wiki/#{link}##{internal_link})"
|
195
|
+
elsif url_options[:source] == "source:"
|
196
|
+
url_options[:name] = url_options[:path] if url_options[:name].empty?
|
197
|
+
"{{#{url_options[:name]}}}(https://github.com/#{git_repo}/#{source_git_path(url_options[:path])})"
|
198
|
+
elsif url_options[:path].start_with?("http")
|
199
|
+
url_options[:name] = url_options[:path] if url_options[:name].empty?
|
200
|
+
"{{#{url_options[:name]}}}(#{url_options[:path]})"
|
201
|
+
else
|
202
|
+
unformatted_text
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def source_git_path(trac_path)
|
207
|
+
trac_path = trac_path.gsub("trunk/", "main/")
|
208
|
+
trac_path = trac_path.delete_prefix("/").delete_suffix("/")
|
209
|
+
|
210
|
+
return "" if trac_path.empty?
|
211
|
+
|
212
|
+
uri = URI.parse(trac_path)
|
213
|
+
|
214
|
+
trac_path = uri.path
|
215
|
+
line_number = uri.fragment
|
216
|
+
trac_path, revision = trac_path.split("@")
|
217
|
+
|
218
|
+
if trac_path.split("/").count <= 1
|
219
|
+
wiki_path(trac_path)
|
220
|
+
else
|
221
|
+
unless trac_path.start_with?("tags")
|
222
|
+
params = CGI.parse(uri.query || "")
|
223
|
+
revision ||= params["rev"].first
|
224
|
+
|
225
|
+
# TODO: Currently @ does not work with file paths except for main branch
|
226
|
+
sha = @revmap[revision]&.strip
|
227
|
+
|
228
|
+
trac_path = if sha && file?(trac_path)
|
229
|
+
trac_path.gsub("main/", "#{sha}/")
|
230
|
+
else
|
231
|
+
sha || trac_path
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
wiki_path(trac_path.delete_prefix("tags/"), line_number)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def index_paths
|
240
|
+
@index_paths ||= {
|
241
|
+
"tags" => "tags",
|
242
|
+
"tags/" => "tags",
|
243
|
+
"branch" => "branches/all"
|
244
|
+
}
|
245
|
+
end
|
246
|
+
|
247
|
+
def file?(trac_path)
|
248
|
+
return false unless trac_path
|
249
|
+
|
250
|
+
@wiki_extensions&.any? { |extension| trac_path.end_with?(extension) }
|
251
|
+
end
|
252
|
+
|
253
|
+
def wiki_path(path, line_number = "")
|
254
|
+
# TODO: This will not work for folders given in the source_folder parameter and
|
255
|
+
# will not work for subfolders paths like `personal/rjs` unless given in the parameters.
|
256
|
+
return "branches/all?query=#{path}" if @source_folders&.any? { |folder| folder == path }
|
257
|
+
return index_paths[path] if index_paths[path]
|
258
|
+
|
259
|
+
prefix = if file?(path)
|
260
|
+
"blob"
|
261
|
+
else
|
262
|
+
"tree"
|
263
|
+
end
|
264
|
+
|
265
|
+
"#{prefix}/#{path}#{"#" unless line_number.to_s.empty?}#{line_number}"
|
266
|
+
end
|
267
|
+
|
268
|
+
# CamelCase page names follow these rules:
|
269
|
+
# 1. The name must consist of alphabetic characters only;
|
270
|
+
# no digits, spaces, punctuation or underscores are allowed.
|
271
|
+
# 2. A name must have at least two capital letters.
|
272
|
+
# 3. The first character must be capitalized.
|
273
|
+
# 4. Every capital letter must be followed by one or more lower-case letters.
|
274
|
+
# 5. The use of slash ( / ) is permitted in page names, where it typically represents a hierarchy.
|
275
|
+
def convert_camel_case_links(str, git_repo)
|
276
|
+
name_regex = %r{(^| )(!?)(/?[A-Z][a-z]+(/?[A-Z][a-z]+)+/?)}
|
277
|
+
wiki_pages_names = Tractive::Wiki.select(:name).distinct.map(:name)
|
278
|
+
str.gsub!(name_regex) do
|
279
|
+
start = Regexp.last_match[2]
|
280
|
+
name = Regexp.last_match[3]
|
281
|
+
|
282
|
+
wiki_link = if start != "!" && wiki_pages_names.include?(name)
|
283
|
+
make_wiki_link(name, git_repo)
|
284
|
+
else
|
285
|
+
name
|
286
|
+
end
|
287
|
+
|
288
|
+
"#{Regexp.last_match[1]}#{wiki_link}"
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
def make_wiki_link(wiki_name, git_repo)
|
293
|
+
wiki_name = "Home" if wiki_name == @home_page_name
|
294
|
+
"[#{wiki_name}](https://github.com/#{git_repo}/wiki/#{wiki_name})"
|
295
|
+
end
|
296
|
+
|
297
|
+
def convert_image(str, base_url, attach_url, wiki_attachments_url, options = {})
|
116
298
|
# https://trac.edgewall.org/wiki/WikiFormatting#Images
|
117
299
|
# [[Image(picture.gif)]] Current page (Ticket, Wiki, Comment)
|
118
300
|
# [[Image(wiki:WikiFormatting:picture.gif)]] (referring to attachment on another page)
|
119
301
|
# [[Image(ticket:1:picture.gif)]] (file attached to a ticket)
|
120
302
|
|
121
303
|
image_regex = /\[\[Image\((?:(?<module>(?:source|wiki)):)?(?<path>[^)]+)\)\]\]/
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
304
|
+
|
305
|
+
str.gsub!(image_regex) do
|
306
|
+
path = Regexp.last_match[:path]
|
307
|
+
mod = Regexp.last_match[:module]
|
308
|
+
|
309
|
+
converted_image = if mod == "source"
|
310
|
+
"!{{#{path.split("/").last}}}(#{base_url}#{path})"
|
311
|
+
elsif mod == "wiki"
|
312
|
+
id, file = path.split(":")
|
313
|
+
upload_path = "#{wiki_attachments_url}/#{Tractive::Utilities.attachment_path(id, file, hashed: @attach_hashed)}"
|
314
|
+
"!{{#{file}}}(#{upload_path})"
|
315
|
+
elsif path.start_with?("http")
|
316
|
+
# [[Image(http://example.org/s.jpg)]]
|
317
|
+
"!{{#{path}}}(#{path})"
|
318
|
+
else
|
319
|
+
tmp = path.split(":")
|
320
|
+
id, file = case tmp.size
|
321
|
+
when 3
|
322
|
+
[tmp[1], tmp[2]]
|
323
|
+
when 2
|
324
|
+
tmp
|
325
|
+
else
|
326
|
+
[options[:id].to_s, tmp[0]]
|
327
|
+
end
|
328
|
+
file_path = "#{attach_url}/#{Tractive::Utilities.attachment_path(id, file, hashed: @attach_hashed)}"
|
329
|
+
"!{{#{path}}}(#{file_path})"
|
330
|
+
end
|
331
|
+
|
332
|
+
# There are also ticket references in the format of ticket:1 so
|
333
|
+
# changing this now and will revert it at the end again
|
334
|
+
converted_image.gsub(/ticket:(\d+)/, 'ImageTicket~\1')
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def revert_intermediate_references(str)
|
339
|
+
str.gsub!(/ImageTicket~(\d)/, 'ticket:\1')
|
340
|
+
str.gsub!("{{", "[")
|
341
|
+
str.gsub!("}}", "]")
|
342
|
+
str.gsub!(/(\{~)*/, "")
|
144
343
|
end
|
145
344
|
end
|
146
345
|
end
|
@@ -13,19 +13,35 @@ module Migrator
|
|
13
13
|
@authors_map = @config["users"].to_h
|
14
14
|
|
15
15
|
@tracticketbaseurl = @config["trac"]["ticketbaseurl"]
|
16
|
+
@git_repo = @config["github"]["repo"]
|
16
17
|
@changeset_base_url = @config["trac"]["changeset_base_url"] || ""
|
18
|
+
@revmap_path = @config["revmap_path"]
|
19
|
+
@attachments_hashed = @config.dig("wiki", "attachments", "hashed")
|
20
|
+
|
17
21
|
@wiki_attachments_url = @options["attachment-base-url"] || @config.dig("wiki", "attachments", "url") || ""
|
18
22
|
@repo_path = @options["repo-path"] || ""
|
19
|
-
@
|
23
|
+
@home_page_name = @options["home-page-name"]
|
24
|
+
@wiki_extensions = @options["wiki-extensions"]
|
25
|
+
@source_folders = @options["source-folders"]
|
20
26
|
|
21
27
|
@attachment_options = {
|
22
|
-
hashed: @
|
28
|
+
hashed: @attachments_hashed
|
23
29
|
}
|
24
30
|
|
25
31
|
verify_options
|
26
32
|
verify_locations
|
27
33
|
|
28
|
-
@twf_to_markdown = Migrator::Converter::TwfToMarkdown.new(
|
34
|
+
@twf_to_markdown = Migrator::Converter::TwfToMarkdown.new(
|
35
|
+
@tracticketbaseurl,
|
36
|
+
@attachment_options,
|
37
|
+
@changeset_base_url,
|
38
|
+
@wiki_attachments_url,
|
39
|
+
@revmap_path,
|
40
|
+
git_repo: @git_repo,
|
41
|
+
home_page_name: @home_page_name,
|
42
|
+
wiki_extensions: @wiki_extensions,
|
43
|
+
source_folders: @source_folders
|
44
|
+
)
|
29
45
|
end
|
30
46
|
|
31
47
|
def migrate_wikis
|
@@ -42,11 +58,13 @@ module Migrator
|
|
42
58
|
wiki[:comment].gsub('"', '\"')
|
43
59
|
end
|
44
60
|
|
45
|
-
file_name =
|
61
|
+
file_name = filename_for_wiki(wiki)
|
62
|
+
|
46
63
|
$logger.info("Working with file [#{file_name}]")
|
47
64
|
$logger.debug("Object: #{wiki}")
|
48
65
|
|
49
|
-
wiki_markdown_text = @twf_to_markdown.convert(wiki[:text])
|
66
|
+
wiki_markdown_text = @twf_to_markdown.convert(wiki[:text], id: wiki[:name])
|
67
|
+
wiki_markdown_text += wiki_attachments(wiki)
|
50
68
|
|
51
69
|
# Create file with content
|
52
70
|
File.open(file_name, "w") do |f|
|
@@ -73,6 +91,12 @@ module Migrator
|
|
73
91
|
|
74
92
|
private
|
75
93
|
|
94
|
+
def filename_for_wiki(wiki)
|
95
|
+
return "Home.md" if @home_page_name == wiki[:name]
|
96
|
+
|
97
|
+
"#{cleanse_filename(wiki[:name])}.md"
|
98
|
+
end
|
99
|
+
|
76
100
|
def verify_options
|
77
101
|
$logger.info("Verifying options...")
|
78
102
|
|
@@ -118,6 +142,22 @@ module Migrator
|
|
118
142
|
"#{author_name} <#{author_email}>"
|
119
143
|
end
|
120
144
|
|
145
|
+
def wiki_attachments(wiki)
|
146
|
+
attachments = wiki.attachments
|
147
|
+
return "" if attachments.count.zero?
|
148
|
+
|
149
|
+
attachments_list = ["# Attachments\n"]
|
150
|
+
|
151
|
+
attachments.each do |attachment|
|
152
|
+
attachment_path = Tractive::Utilities.attachment_path(
|
153
|
+
wiki.name, attachment.filename, hashed: @attachments_hashed
|
154
|
+
)
|
155
|
+
attachments_list << "- [#{attachment.filename}](#{@wiki_attachments_url}/#{attachment_path})"
|
156
|
+
end
|
157
|
+
|
158
|
+
attachments_list.join("\n")
|
159
|
+
end
|
160
|
+
|
121
161
|
def execute_command(command)
|
122
162
|
`#{command}`
|
123
163
|
$CHILD_STATUS
|
data/lib/tractive/utilities.rb
CHANGED
data/lib/tractive/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tractive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mysql2
|