tractive 1.0.7 → 1.0.11
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/.rubocop.yml +3 -0
- data/README.adoc +80 -16
- data/db/trac-test.db +0 -0
- data/exe/command_base.rb +11 -0
- data/exe/generate.rb +49 -0
- data/exe/tractive +19 -51
- data/lib/tractive/github_api/client/issues.rb +6 -6
- data/lib/tractive/github_api/client/labels.rb +2 -2
- data/lib/tractive/github_api/client/milestones.rb +2 -2
- data/lib/tractive/github_api/client.rb +2 -0
- data/lib/tractive/http/client/request.rb +59 -0
- data/lib/tractive/http/client.rb +3 -0
- data/lib/tractive/main.rb +5 -1
- data/lib/tractive/migrator/converter/trac_to_github.rb +26 -12
- data/lib/tractive/migrator/converter/twf_to_markdown.rb +7 -5
- data/lib/tractive/migrator/engine.rb +4 -3
- data/lib/tractive/migrator/wikis/migrate_from_db.rb +145 -0
- data/lib/tractive/migrator/wikis.rb +3 -0
- data/lib/tractive/migrator.rb +1 -0
- data/lib/tractive/models/attachment.rb +1 -0
- data/lib/tractive/models/ticket.rb +16 -8
- data/lib/tractive/models/wiki.rb +18 -0
- data/lib/tractive/trac.rb +2 -1
- data/lib/tractive/utilities.rb +14 -2
- data/lib/tractive/version.rb +1 -1
- data/lib/tractive.rb +1 -0
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ebb8048967ee1732b68d54ed6c10798e0959d533e7ed9744a843f1a129f764d
|
4
|
+
data.tar.gz: 4799587764dcaa848e76971b50df220e72ffa914a5f1bc7c3cad20ef2e5de83d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c052a1f936f6e4d4749e4fd9f8ec9fcab3042f4220e2c4f10e6a7ed127f2c1ee8a856f49a58ae8b960a38f12ffdc35d9097a55361142b39bfa605a269ea2d1b
|
7
|
+
data.tar.gz: 6d0025c7682c74526aa3a0fb8a4d93d4f46fad4cab5e560898e3b2c504e8981cffe10203e59afb7c8d818d3598efe3729b854c2939d7b8ca64105846de55f131
|
data/.rubocop.yml
CHANGED
data/README.adoc
CHANGED
@@ -174,7 +174,7 @@ With this information you can now build the RevMap with:
|
|
174
174
|
|
175
175
|
[source,sh]
|
176
176
|
----
|
177
|
-
tractive generate
|
177
|
+
tractive generate revmap \
|
178
178
|
--svn-url <url of the SVN repository> \
|
179
179
|
--rev-timestamp-file <reposurgeon timestamp map, e.g. {name-of-repo}.fo> \
|
180
180
|
--git-local-repo-path <path to converted Git repository, e.g. {name-of-repo}-git> \
|
@@ -186,7 +186,7 @@ issues and commits will replace references to SVN revisions with the
|
|
186
186
|
corresponding Git commit SHA, enabling GitHub to expose those linkages in the
|
187
187
|
user interface.
|
188
188
|
|
189
|
-
.Options for `tractive generate
|
189
|
+
.Options for `tractive generate revmap` command
|
190
190
|
[cols="3a,5a,2a",options="header"]
|
191
191
|
|===
|
192
192
|
| Option | Description | Type
|
@@ -315,7 +315,7 @@ e.g. 'ghp_fpsc4de1f0c46e01576810740c9242097cba4619486'.
|
|
315
315
|
e.g. '/Users/user/repo-git'.
|
316
316
|
|
317
317
|
`revmap_path:`::: Local path to the RevMap file generated via the
|
318
|
-
`tractive generate
|
318
|
+
`tractive generate revmap` command.
|
319
319
|
|
320
320
|
|
321
321
|
EXAMPLE:
|
@@ -326,7 +326,8 @@ github:
|
|
326
326
|
repo: 'example-org/target-repository'
|
327
327
|
token: 'ghp_fpsc4de1f0c46e01576810740c9242097cba4619486'
|
328
328
|
local_repo_path: '/Users/user/repo-git'
|
329
|
-
|
329
|
+
|
330
|
+
revmap_path: ./example-revmap.txt
|
330
331
|
----
|
331
332
|
|
332
333
|
|
@@ -359,8 +360,12 @@ The pattern of a mapping is like:
|
|
359
360
|
+
|
360
361
|
[source,yaml]
|
361
362
|
----
|
362
|
-
configuration:
|
363
|
-
|
363
|
+
configuration:
|
364
|
+
name: conf
|
365
|
+
color: ff00ff
|
366
|
+
documentation:
|
367
|
+
name: doc
|
368
|
+
color: 00ff00
|
364
369
|
----
|
365
370
|
|
366
371
|
`resolution:`::: Resolution of the Trac ticket. e.g.
|
@@ -433,7 +438,7 @@ The pattern of a mapping is like:
|
|
433
438
|
----
|
434
439
|
|
435
440
|
|
436
|
-
NOTE: As `severity`, `priority` and `tracstate` are converted into `labels` on github so there is an option to specify the `color` for those labels.
|
441
|
+
NOTE: As `component`, `severity`, `priority` and `tracstate` are converted into `labels` on github so there is an option to specify the `color` for those labels.
|
437
442
|
|
438
443
|
|
439
444
|
==== User mapping
|
@@ -499,22 +504,32 @@ milestones:
|
|
499
504
|
|
500
505
|
|
501
506
|
==== Attachments migration configuration
|
507
|
+
`ticket | wiki:`:: specifies the options for the tickets or wikis
|
508
|
+
|
509
|
+
`attachments:`::: specifies method of obtaining attachments from Trac.
|
502
510
|
|
503
|
-
`
|
511
|
+
`url:`:::: URL to obtain Trac attachments from
|
504
512
|
|
505
|
-
`url
|
513
|
+
`hashed:`:::: Whether the url has hased or plain image names and ids
|
506
514
|
|
507
|
-
`export_folder
|
515
|
+
`export_folder:`:::: folder where the attachments will be downloaded to from Trac.
|
508
516
|
|
509
|
-
`export_script
|
510
|
-
all attachments from Trac.
|
517
|
+
`export_script:`:::: output of a script that utilizes `trac-admin` to download
|
518
|
+
all attachments from Trac.
|
511
519
|
|
512
520
|
[source,yaml]
|
513
521
|
----
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
522
|
+
ticket:
|
523
|
+
attachments:
|
524
|
+
url: https://abc.com/raw-attachment/ticket
|
525
|
+
hashed: true
|
526
|
+
export_folder: ./attachments
|
527
|
+
export_script: attachments.sh
|
528
|
+
|
529
|
+
wiki:
|
530
|
+
attachments:
|
531
|
+
url: https://abc.com/raw-attachment/wiki
|
532
|
+
hashed: true
|
518
533
|
----
|
519
534
|
|
520
535
|
By using the <<gather-info,`-i` option>>, you can easily produce a YAML file
|
@@ -682,6 +697,7 @@ The following options are allowed (at least one necessary):
|
|
682
697
|
* `column-name`
|
683
698
|
* `operator`
|
684
699
|
* `column-value`
|
700
|
+
* `include-null`
|
685
701
|
|
686
702
|
| Boolean
|
687
703
|
|
@@ -697,6 +713,10 @@ The following options are allowed (at least one necessary):
|
|
697
713
|
| Value of the column to filter.
|
698
714
|
| String
|
699
715
|
|
716
|
+
| `--include-null`
|
717
|
+
| Include rows having null value in filtered column.
|
718
|
+
| Boolean
|
719
|
+
|
700
720
|
| `-h`, `help`
|
701
721
|
| Display the Tractive help message, or you can provide a command to know more
|
702
722
|
about a single command via `tractive help {command}`.
|
@@ -741,6 +761,50 @@ The following options are allowed (at least one necessary):
|
|
741
761
|
|===
|
742
762
|
|
743
763
|
|
764
|
+
=== Migrating Wikis
|
765
|
+
|
766
|
+
You need the following for wiki migration
|
767
|
+
|
768
|
+
* Clone of the github wiki repo.
|
769
|
+
|
770
|
+
Then you can run the migration with:
|
771
|
+
|
772
|
+
[source,sh]
|
773
|
+
----
|
774
|
+
tractive migrate-wikis \
|
775
|
+
--attachment-base-url <url for the attachments> \
|
776
|
+
--trac-database-path <full path of trac database> \
|
777
|
+
--repo-path <path to cloned Git wiki repository, e.g. {name-of-repo}.wiki>
|
778
|
+
----
|
779
|
+
|
780
|
+
After that open a terminal in the git wiki folder and run `git push`
|
781
|
+
|
782
|
+
.Options for `tractive migrate-wikis` command
|
783
|
+
[cols="3a,5a,2a",options="header"]
|
784
|
+
|===
|
785
|
+
| Option | Description | Type
|
786
|
+
|
787
|
+
| `a`, `--attachment-base-url`
|
788
|
+
|
|
789
|
+
(required unless specified in config file)
|
790
|
+
If attachment files are reachable via a URL we reference this here.
|
791
|
+
| String
|
792
|
+
|
793
|
+
| `-d`, `--trac-database-path`
|
794
|
+
| (required unless specified in config file) Full path of the Trac sqlite3 database export file.
|
795
|
+
| String
|
796
|
+
|
797
|
+
| `-r`, `--repo-path`
|
798
|
+
| (required) Full path to the root of the git-repository that is our destination.
|
799
|
+
| String
|
800
|
+
|
801
|
+
| `-c`, `--config`
|
802
|
+
| Path to config file.
|
803
|
+
| String
|
804
|
+
|
805
|
+
|===
|
806
|
+
|
807
|
+
|
744
808
|
== Implementation details
|
745
809
|
|
746
810
|
=== Usage of GitHub Issue Import API
|
data/db/trac-test.db
CHANGED
Binary file
|
data/exe/command_base.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../lib/tractive"
|
4
|
+
|
5
|
+
class CommandBase < Thor
|
6
|
+
class_option "logfile", type: :string, aliases: ["-L", "--log-file"],
|
7
|
+
desc: "Name of the logfile to output logs to."
|
8
|
+
class_option "config", type: :string, default: "tractive.config.yaml", banner: "<PATH>", aliases: "-c",
|
9
|
+
desc: "Set the configuration file"
|
10
|
+
class_option "verbose", type: :boolean, aliases: ["-v", "--verbose"], desc: "Verbose mode"
|
11
|
+
end
|
data/exe/generate.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./command_base"
|
4
|
+
|
5
|
+
class Generate < CommandBase
|
6
|
+
desc "revmap <OPTIONS>", "Generate a mapping from svn revision number to git sha hash."
|
7
|
+
method_option "svnurl", type: :string, aliases: ["--svn-url"],
|
8
|
+
desc: "Svn url that should be used in revmap generation"
|
9
|
+
method_option "svnlocalpath", type: :string, aliases: ["--svn-local-path"],
|
10
|
+
desc: "Local SVN repo path"
|
11
|
+
method_option "gitlocalrepopath", type: :string, aliases: ["--git-local-repo-path"],
|
12
|
+
desc: "Local git repo path that should be used in revmap generation"
|
13
|
+
method_option "revtimestampfile", type: :string, aliases: ["--rev-timestamp-file"],
|
14
|
+
desc: "File containing svn revision and timestamps that should be used in revmap generation"
|
15
|
+
method_option "revoutputfile", type: :string, aliases: ["--revmap-output-file"],
|
16
|
+
desc: "File to output the generated revmap"
|
17
|
+
def revmap
|
18
|
+
verify_revmap_generator_options!(options)
|
19
|
+
|
20
|
+
Tractive::Utilities.setup_logger(output_stream: options[:log_file] || $stderr, verbose: options[:verbose])
|
21
|
+
Tractive::RevmapGenerator.new(
|
22
|
+
options["revtimestampfile"],
|
23
|
+
options["svnurl"],
|
24
|
+
options["svnlocalpath"],
|
25
|
+
options["gitlocalrepopath"],
|
26
|
+
options["revoutputfile"]
|
27
|
+
).generate
|
28
|
+
end
|
29
|
+
|
30
|
+
no_commands do
|
31
|
+
def verify_revmap_generator_options!(options)
|
32
|
+
required_options = {}
|
33
|
+
required_options["--svn-url OR --svn-local-path"] = options["svnurl"] || options["svnlocalpath"]
|
34
|
+
required_options["--git-local-repo-path"] = options["gitlocalrepopath"]
|
35
|
+
required_options["--rev-timestamp-file"] = options["revtimestampfile"]
|
36
|
+
required_options["--revmap-output-file"] = options["revoutputfile"]
|
37
|
+
|
38
|
+
missing_options = {}
|
39
|
+
required_options.each do |key, value|
|
40
|
+
missing_options[key] = value if value.nil? || value.strip.empty?
|
41
|
+
end
|
42
|
+
|
43
|
+
return if missing_options.empty?
|
44
|
+
|
45
|
+
warn("missing revmap generator options (#{missing_options.keys}).\nRun with `--help` or `-h` to see available options")
|
46
|
+
exit 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/exe/tractive
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require_relative "
|
4
|
+
require_relative "./command_base"
|
5
|
+
require_relative "./generate"
|
5
6
|
|
6
|
-
class TractiveCommand <
|
7
|
-
default_command :
|
8
|
-
|
9
|
-
|
7
|
+
class TractiveCommand < CommandBase
|
8
|
+
default_command :migrate_tickets
|
9
|
+
|
10
|
+
desc "generate", "Generate different files/scripts"
|
11
|
+
subcommand "generate", Generate
|
10
12
|
|
11
13
|
desc "<OPTIONS>", "Migrate Trac instances to modern Git management platforms like GitHub and GitLab"
|
12
14
|
method_option "attachmentexporter", type: :string, aliases: ["-A", "--attachment-exporter"],
|
13
15
|
desc: "Generate an attachment exporter script according to config.yaml"
|
14
16
|
method_option "attachurl", type: :string, aliases: ["-a", "--attachment-url"], banner: "<URL>",
|
15
17
|
desc: "If attachment files are reachable via a URL we reference this here"
|
16
|
-
method_option "config", type: :string, default: "tractive.config.yaml", banner: "<PATH>", aliases: "-c",
|
17
|
-
desc: "Set the configuration file"
|
18
18
|
method_option "dryrun", type: :boolean, aliases: ["-d", "--dry-run"],
|
19
19
|
desc: "Write data to a file instead of pushing it to github"
|
20
20
|
method_option "exportattachments", type: :string, aliases: ["-e", "--export-attachments"],
|
@@ -30,6 +30,8 @@ class TractiveCommand < Thor
|
|
30
30
|
desc: "Operator for filter."
|
31
31
|
method_option "columnvalue", type: :string, aliases: ["--column-value"],
|
32
32
|
desc: "Value of the column to filter."
|
33
|
+
method_option "includenull", type: :boolean, aliases: ["--include-null"],
|
34
|
+
desc: "Flag for including null values in the filter result."
|
33
35
|
|
34
36
|
method_option "importfromfile", type: :string, aliases: ["-I", "--import-from-file"],
|
35
37
|
desc: "Import issues from a json file"
|
@@ -45,33 +47,19 @@ class TractiveCommand < Thor
|
|
45
47
|
desc: "Put all issue comments in the first message."
|
46
48
|
method_option "start", type: :numeric, aliases: ["-s", "--start-at"], banner: "<ID>",
|
47
49
|
desc: "Start migration from ticket with number <ID>"
|
48
|
-
|
49
|
-
def migrate
|
50
|
+
def migrate_tickets
|
50
51
|
Tractive::Main.new(options).run
|
51
52
|
end
|
52
53
|
|
53
|
-
desc "
|
54
|
-
method_option "
|
55
|
-
|
56
|
-
method_option "
|
57
|
-
|
58
|
-
method_option "
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
method_option "revoutputfile", type: :string, aliases: ["--revmap-output-file"],
|
63
|
-
desc: "File to output the generated revmap"
|
64
|
-
def generate_revmap
|
65
|
-
verify_revmap_generator_options!(options)
|
66
|
-
|
67
|
-
Tractive::Utilities.setup_logger(output_stream: options[:log_file] || $stderr, verbose: options[:verbose])
|
68
|
-
Tractive::RevmapGenerator.new(
|
69
|
-
options["revtimestampfile"],
|
70
|
-
options["svnurl"],
|
71
|
-
options["svnlocalpath"],
|
72
|
-
options["gitlocalrepopath"],
|
73
|
-
options["revoutputfile"]
|
74
|
-
).generate
|
54
|
+
desc "migrate-wikis", "Migrate Trac wikis to a git repository, preserving history (including authors, dates, and comments)"
|
55
|
+
method_option "attachment-base-url", type: :string, aliases: ["-a"], banner: "http://<base-url>",
|
56
|
+
desc: "If attachment files are reachable via a URL we reference this here"
|
57
|
+
method_option "trac-database-path", type: :string, aliases: ["-d"], banner: "/PATH/TO/EXPORTFILE",
|
58
|
+
desc: "Full path of the Trac sqlite3 database export file"
|
59
|
+
method_option "repo-path", type: :string, aliases: ["-r"], banner: "/GIT/ROOT/DIR",
|
60
|
+
desc: "Full path to the root of the git-repository that is our destination"
|
61
|
+
def migrate_wikis
|
62
|
+
Tractive::Main.new(options).migrate_wikis
|
75
63
|
end
|
76
64
|
|
77
65
|
def self.exit_on_failure?
|
@@ -87,26 +75,6 @@ class TractiveCommand < Thor
|
|
87
75
|
def respond_to_missing?
|
88
76
|
true
|
89
77
|
end
|
90
|
-
|
91
|
-
no_commands do
|
92
|
-
def verify_revmap_generator_options!(options)
|
93
|
-
required_options = {}
|
94
|
-
required_options["--svn-url OR --svn-local-path"] = options["svnurl"] || options["svnlocalpath"]
|
95
|
-
required_options["--git-local-repo-path"] = options["gitlocalrepopath"]
|
96
|
-
required_options["--rev-timestamp-file"] = options["revtimestampfile"]
|
97
|
-
required_options["--revmap-output-file"] = options["revoutputfile"]
|
98
|
-
|
99
|
-
missing_options = {}
|
100
|
-
required_options.each do |key, value|
|
101
|
-
missing_options[key] = value if value.nil? || value.strip.empty?
|
102
|
-
end
|
103
|
-
|
104
|
-
return if missing_options.empty?
|
105
|
-
|
106
|
-
warn("missing revmap generator options (#{missing_options.keys}).\nRun with `--help` or `-h` to see available options")
|
107
|
-
exit 1
|
108
|
-
end
|
109
|
-
end
|
110
78
|
end
|
111
79
|
|
112
80
|
TractiveCommand.start(ARGV)
|
@@ -6,7 +6,7 @@ module GithubApi
|
|
6
6
|
module Issues
|
7
7
|
def create_issue(repo, params)
|
8
8
|
JSON.parse(
|
9
|
-
|
9
|
+
Http::Client::Request.post(
|
10
10
|
"https://api.github.com/repos/#{repo}/import/issues",
|
11
11
|
params.to_json,
|
12
12
|
{
|
@@ -20,7 +20,7 @@ module GithubApi
|
|
20
20
|
|
21
21
|
def list_issues(repo, params)
|
22
22
|
JSON.parse(
|
23
|
-
|
23
|
+
Http::Client::Request.get(
|
24
24
|
"https://api.github.com/repos/#{repo}/issues",
|
25
25
|
{
|
26
26
|
"Authorization" => "token #{@token}",
|
@@ -33,7 +33,7 @@ module GithubApi
|
|
33
33
|
|
34
34
|
def issue(repo, number)
|
35
35
|
JSON.parse(
|
36
|
-
|
36
|
+
Http::Client::Request.get(
|
37
37
|
"https://api.github.com/repos/#{repo}/issues/#{number}",
|
38
38
|
{ "Authorization" => "token #{@token}" }
|
39
39
|
)
|
@@ -42,7 +42,7 @@ module GithubApi
|
|
42
42
|
|
43
43
|
def issue_import_status(repo, id)
|
44
44
|
JSON.parse(
|
45
|
-
|
45
|
+
Http::Client::Request.get(
|
46
46
|
"https://api.github.com/repos/#{repo}/import/issues/#{id}",
|
47
47
|
{
|
48
48
|
"Authorization" => "token #{@token}",
|
@@ -54,7 +54,7 @@ module GithubApi
|
|
54
54
|
|
55
55
|
def issue_comments(repo, issue_id)
|
56
56
|
JSON.parse(
|
57
|
-
|
57
|
+
Http::Client::Request.get(
|
58
58
|
"https://api.github.com/repos/#{repo}/issues/#{issue_id}/comments",
|
59
59
|
{
|
60
60
|
"Authorization" => "token #{@token}",
|
@@ -66,7 +66,7 @@ module GithubApi
|
|
66
66
|
|
67
67
|
def update_issue_comment(repo, comment_id, comment_body)
|
68
68
|
JSON.parse(
|
69
|
-
|
69
|
+
Http::Client::Request.patch(
|
70
70
|
"https://api.github.com/repos/#{repo}/issues/comments/#{comment_id}",
|
71
71
|
{ body: comment_body }.to_json,
|
72
72
|
{ "Authorization" => "token #{@token}" }
|
@@ -5,7 +5,7 @@ module GithubApi
|
|
5
5
|
module Labels
|
6
6
|
def list_labels(repo, params = {})
|
7
7
|
JSON.parse(
|
8
|
-
|
8
|
+
Http::Client::Request.get(
|
9
9
|
"https://api.github.com/repos/#{repo}/labels",
|
10
10
|
{
|
11
11
|
"Authorization" => "token #{@token}",
|
@@ -18,7 +18,7 @@ module GithubApi
|
|
18
18
|
|
19
19
|
def create_label(repo, params)
|
20
20
|
JSON.parse(
|
21
|
-
|
21
|
+
Http::Client::Request.post(
|
22
22
|
"https://api.github.com/repos/#{repo}/labels",
|
23
23
|
params.to_json,
|
24
24
|
{
|
@@ -6,7 +6,7 @@ module GithubApi
|
|
6
6
|
module Milestones
|
7
7
|
def list_milestones(repo, params)
|
8
8
|
JSON.parse(
|
9
|
-
|
9
|
+
Http::Client::Request.get(
|
10
10
|
"https://api.github.com/repos/#{repo}/milestones?per_page=100",
|
11
11
|
{
|
12
12
|
"Authorization" => "token #{@token}",
|
@@ -19,7 +19,7 @@ module GithubApi
|
|
19
19
|
|
20
20
|
def create_milestone(repo, params)
|
21
21
|
JSON.parse(
|
22
|
-
|
22
|
+
Http::Client::Request.post(
|
23
23
|
"https://api.github.com/repos/#{repo}/milestones",
|
24
24
|
params.to_json,
|
25
25
|
{
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Http
|
4
|
+
module Client
|
5
|
+
class Request
|
6
|
+
def initialize(args)
|
7
|
+
@args = args
|
8
|
+
@max_retries = args[:max_retries] || 3
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute(&block)
|
12
|
+
retries = 0
|
13
|
+
|
14
|
+
begin
|
15
|
+
retries += 1
|
16
|
+
RestClient::Request.execute(@args, &block)
|
17
|
+
rescue RestClient::Forbidden => e
|
18
|
+
retry_after = e.http_headers[:x_ratelimit_reset].to_i - Time.now.to_i
|
19
|
+
raise e if retry_after.negative? || retries > @max_retries
|
20
|
+
|
21
|
+
while retry_after.positive?
|
22
|
+
minutes = retry_after / 60
|
23
|
+
seconds = retry_after % 60
|
24
|
+
|
25
|
+
print "\rRate Limit Exceeded, Will retry in #{minutes} min #{seconds} sec"
|
26
|
+
sleep(1)
|
27
|
+
|
28
|
+
retry_after = e.http_headers[:x_ratelimit_reset].to_i - Time.now.to_i
|
29
|
+
end
|
30
|
+
retry if retries <= @max_retries
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :response
|
35
|
+
|
36
|
+
class << self
|
37
|
+
def get(url, headers = {}, &block)
|
38
|
+
execute(method: :get, url: url, headers: headers, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
def post(url, payload, headers = {}, &block)
|
42
|
+
execute(method: :post, url: url, payload: payload, headers: headers, &block)
|
43
|
+
end
|
44
|
+
|
45
|
+
def put(url, payload, headers = {}, &block)
|
46
|
+
execute(method: :put, url: url, payload: payload, headers: headers, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def patch(url, payload, headers = {}, &block)
|
50
|
+
execute(method: :patch, url: url, payload: payload, headers: headers, &block)
|
51
|
+
end
|
52
|
+
|
53
|
+
def execute(args, &block)
|
54
|
+
new(args).execute(&block)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/tractive/main.rb
CHANGED
@@ -9,7 +9,7 @@ module Tractive
|
|
9
9
|
@cfg = YAML.load_file(@opts[:config])
|
10
10
|
|
11
11
|
Tractive::Utilities.setup_logger(output_stream: @opts[:logfile] || $stderr, verbose: @opts[:verbose])
|
12
|
-
@db = Tractive::Utilities.setup_db!(@cfg["trac"]["database"])
|
12
|
+
@db = Tractive::Utilities.setup_db!(@opts["trac-database-path"] || @cfg["trac"]["database"])
|
13
13
|
rescue Sequel::DatabaseConnectionError, Sequel::AdapterNotFound, URI::InvalidURIError, Sequel::DatabaseError => e
|
14
14
|
$logger.error e.message
|
15
15
|
exit 1
|
@@ -33,6 +33,10 @@ module Tractive
|
|
33
33
|
Migrator::Engine.new(opts: @opts, cfg: @cfg, db: @db).migrate
|
34
34
|
end
|
35
35
|
|
36
|
+
def migrate_wikis
|
37
|
+
Migrator::Wikis::MigrateFromDb.new(opts: @opts, cfg: @cfg).migrate_wikis
|
38
|
+
end
|
39
|
+
|
36
40
|
def info
|
37
41
|
Tractive::Info.new.print
|
38
42
|
end
|
@@ -4,8 +4,8 @@ module Migrator
|
|
4
4
|
module Converter
|
5
5
|
class TracToGithub
|
6
6
|
def initialize(args)
|
7
|
-
@
|
8
|
-
@attachurl = args[:opts][:attachurl] || args[:cfg].dig("attachments", "url")
|
7
|
+
@trac_ticket_base_url = args[:cfg]["trac"]["ticketbaseurl"]
|
8
|
+
@attachurl = args[:opts][:attachurl] || args[:cfg].dig("ticket", "attachments", "url")
|
9
9
|
@changeset_base_url = args[:cfg]["trac"]["changeset_base_url"] || ""
|
10
10
|
@singlepost = args[:opts][:singlepost]
|
11
11
|
@labels_cfg = args[:cfg]["labels"].transform_values(&:to_h)
|
@@ -14,8 +14,12 @@ module Migrator
|
|
14
14
|
@trac_mails_cache = {}
|
15
15
|
@repo = args[:cfg]["github"]["repo"]
|
16
16
|
@client = GithubApi::Client.new(access_token: args[:cfg]["github"]["token"])
|
17
|
-
@wiki_attachments_url = args[:cfg]
|
17
|
+
@wiki_attachments_url = args[:cfg].dig("wiki", "attachments", "url")
|
18
18
|
@revmap_file_path = args[:opts][:revmapfile] || args[:cfg]["revmap_path"]
|
19
|
+
@attachment_options = {
|
20
|
+
url: @attachurl,
|
21
|
+
hashed: args[:cfg].dig("ticket", "attachments", "hashed")
|
22
|
+
}
|
19
23
|
|
20
24
|
load_milestone_map
|
21
25
|
create_labels_on_github(@labels_cfg["severity"].values)
|
@@ -24,12 +28,18 @@ module Migrator
|
|
24
28
|
create_labels_on_github(@labels_cfg["component"].values)
|
25
29
|
|
26
30
|
@uri_parser = URI::Parser.new
|
27
|
-
@twf_to_markdown = Migrator::Converter::TwfToMarkdown.new(
|
31
|
+
@twf_to_markdown = Migrator::Converter::TwfToMarkdown.new(
|
32
|
+
@trac_ticket_base_url,
|
33
|
+
@attachment_options,
|
34
|
+
@changeset_base_url,
|
35
|
+
@wiki_attachments_url,
|
36
|
+
@revmap_file_path
|
37
|
+
)
|
28
38
|
end
|
29
39
|
|
30
40
|
def compose(ticket)
|
31
|
-
body
|
32
|
-
|
41
|
+
body = ""
|
42
|
+
closed_time = nil
|
33
43
|
|
34
44
|
# summary line:
|
35
45
|
# body += %i[id component priority resolution].map do |cat|
|
@@ -70,7 +80,7 @@ module Migrator
|
|
70
80
|
@labels_cfg.fetch(x[:field], {})[x[:newvalue]]
|
71
81
|
labels.delete(del) if del
|
72
82
|
# labels.add(add) if add
|
73
|
-
|
83
|
+
closed_time = x[:time] if x[:field] == "status" && x[:newvalue] == "closed"
|
74
84
|
end
|
75
85
|
|
76
86
|
# we separate labels from badges
|
@@ -149,8 +159,12 @@ module Migrator
|
|
149
159
|
# issue["updated_at"] = format_time(ticket[:changetime])
|
150
160
|
end
|
151
161
|
|
152
|
-
if issue["closed"]
|
153
|
-
|
162
|
+
if issue["closed"]
|
163
|
+
issue["closed_at"] = if closed_time
|
164
|
+
format_time(closed_time)
|
165
|
+
else
|
166
|
+
format_time(ticket[:closed_at].to_i)
|
167
|
+
end
|
154
168
|
end
|
155
169
|
|
156
170
|
{
|
@@ -287,7 +301,7 @@ module Migrator
|
|
287
301
|
name = meta[:filename]
|
288
302
|
body = meta[:description]
|
289
303
|
if @attachurl
|
290
|
-
url = @uri_parser.escape("#{@attachurl}/#{meta[:id]
|
304
|
+
url = @uri_parser.escape("#{@attachurl}/#{Tractive::Utilities.attachment_path(meta[:id], name, @attachment_options)}")
|
291
305
|
text += "[`#{name}`](#{url})"
|
292
306
|
body += "\n" if [".png", ".jpg", ".gif"].include? File.extname(name).downcase
|
293
307
|
else
|
@@ -335,9 +349,9 @@ module Migrator
|
|
335
349
|
end
|
336
350
|
|
337
351
|
def trac_ticket_link(ticket)
|
338
|
-
return "trac:#{ticket[:id]}" unless @
|
352
|
+
return "trac:#{ticket[:id]}" unless @trac_ticket_base_url
|
339
353
|
|
340
|
-
"[trac:#{ticket[:id]}](#{@
|
354
|
+
"[trac:#{ticket[:id]}](#{@trac_ticket_base_url}/#{ticket[:id]})"
|
341
355
|
end
|
342
356
|
end
|
343
357
|
end
|
@@ -4,9 +4,10 @@ module Migrator
|
|
4
4
|
module Converter
|
5
5
|
# twf => Trac wiki format
|
6
6
|
class TwfToMarkdown
|
7
|
-
def initialize(base_url,
|
7
|
+
def initialize(base_url, attachment_options, changeset_base_url, wiki_attachments_url, revmap_file_path)
|
8
8
|
@base_url = base_url
|
9
|
-
@attach_url =
|
9
|
+
@attach_url = attachment_options[:url]
|
10
|
+
@attach_hashed = attachment_options[:hashed]
|
10
11
|
@changeset_base_url = changeset_base_url
|
11
12
|
@wiki_attachments_url = wiki_attachments_url
|
12
13
|
@revmap = load_revmap_file(revmap_file_path)
|
@@ -95,6 +96,7 @@ module Migrator
|
|
95
96
|
str.gsub!(/\[changeset:"(\d+)".*\]/) { Tractive::Utilities.map_changeset(Regexp.last_match[1], @revmap, changeset_base_url) }
|
96
97
|
str.gsub!(/\[changeset:(\d+).*\]/) { Tractive::Utilities.map_changeset(Regexp.last_match[1], @revmap, changeset_base_url) }
|
97
98
|
str.gsub!(/\[(\d+)\]/) { Tractive::Utilities.map_changeset(Regexp.last_match[1], @revmap, changeset_base_url) }
|
99
|
+
str.gsub!(%r{\[(\d+)/.*\]}) { Tractive::Utilities.map_changeset(Regexp.last_match[1], @revmap, changeset_base_url) }
|
98
100
|
end
|
99
101
|
|
100
102
|
# Font styles
|
@@ -126,15 +128,15 @@ module Migrator
|
|
126
128
|
image_path = if mod == "source"
|
127
129
|
""
|
128
130
|
elsif mod == "wiki"
|
129
|
-
|
130
|
-
upload_path = "#{wiki_attachments_url}/#{file}"
|
131
|
+
id, file = path.split(":")
|
132
|
+
upload_path = "#{wiki_attachments_url}/#{Tractive::Utilities.attachment_path(id, file, hashed: @attach_hashed)}"
|
131
133
|
""
|
132
134
|
elsif path.start_with?("http")
|
133
135
|
# [[Image(http://example.org/s.jpg)]]
|
134
136
|
"![#{d[:path]}](#{d[:path]})"
|
135
137
|
else
|
136
138
|
_, id, file = path.split(":")
|
137
|
-
file_path = "#{attach_url}/#{id
|
139
|
+
file_path = "#{attach_url}/#{Tractive::Utilities.attachment_path(id, file, hashed: @attach_hashed)}"
|
138
140
|
"![#{d[:path]}](#{file_path})"
|
139
141
|
end
|
140
142
|
|
@@ -27,7 +27,7 @@ module Migrator
|
|
27
27
|
input_file_name = args[:opts][:importfromfile]
|
28
28
|
|
29
29
|
@filter_applied = args[:opts][:filter]
|
30
|
-
@filter_options = { column_name: args[:opts][:columnname], operator: args[:opts][:operator], column_value: args[:opts][:columnvalue] }
|
30
|
+
@filter_options = { column_name: args[:opts][:columnname], operator: args[:opts][:operator], column_value: args[:opts][:columnvalue], include_null: args[:opts][:includenull] }
|
31
31
|
|
32
32
|
@trac = Tractive::Trac.new(db)
|
33
33
|
@repo = github["repo"]
|
@@ -96,7 +96,7 @@ module Migrator
|
|
96
96
|
|
97
97
|
def mock_ticket_details(ticket_id)
|
98
98
|
summary = if @filter_applied
|
99
|
-
"
|
99
|
+
"Placeholder issue #{ticket_id} created to align Github issue and trac ticket numbers during migration."
|
100
100
|
else
|
101
101
|
"DELETED in trac #{ticket_id}"
|
102
102
|
end
|
@@ -105,7 +105,8 @@ module Migrator
|
|
105
105
|
summary: summary,
|
106
106
|
time: Time.now.to_i,
|
107
107
|
status: "closed",
|
108
|
-
reporter: "tractive"
|
108
|
+
reporter: "tractive",
|
109
|
+
closed_at: Time.at(0).utc
|
109
110
|
}
|
110
111
|
end
|
111
112
|
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "csv"
|
4
|
+
|
5
|
+
module Migrator
|
6
|
+
module Wikis
|
7
|
+
class MigrateFromDb
|
8
|
+
def initialize(args)
|
9
|
+
$logger.debug("OPTIONS = #{args}")
|
10
|
+
|
11
|
+
@config = args[:cfg]
|
12
|
+
@options = args[:opts]
|
13
|
+
@authors_map = @config["users"].to_h
|
14
|
+
|
15
|
+
@tracticketbaseurl = @config["trac"]["ticketbaseurl"]
|
16
|
+
@changeset_base_url = @config["trac"]["changeset_base_url"] || ""
|
17
|
+
@wiki_attachments_url = @options["attachment-base-url"] || @config.dig("wiki", "attachments", "url") || ""
|
18
|
+
@repo_path = @options["repo-path"] || ""
|
19
|
+
@revmap_path = @config["revmap_path"]
|
20
|
+
@attachments_hashed = @config.dig("wiki", "attachments", "hashed")
|
21
|
+
|
22
|
+
@attachment_options = {
|
23
|
+
hashed: @attachments_hashed
|
24
|
+
}
|
25
|
+
|
26
|
+
verify_options
|
27
|
+
verify_locations
|
28
|
+
|
29
|
+
@twf_to_markdown = Migrator::Converter::TwfToMarkdown.new(@tracticketbaseurl, @attachment_options, @changeset_base_url, @wiki_attachments_url, @revmap_path)
|
30
|
+
end
|
31
|
+
|
32
|
+
def migrate_wikis
|
33
|
+
$logger.info("Processing the wiki...")
|
34
|
+
|
35
|
+
Dir.chdir(@options["repo-path"]) do
|
36
|
+
# For every version of every file in the wiki...
|
37
|
+
Tractive::Wiki.for_migration.each do |wiki|
|
38
|
+
next if skip_file(wiki[:name])
|
39
|
+
|
40
|
+
comment = if wiki[:comment].nil? || wiki[:comment].empty?
|
41
|
+
"Initial load of version #{wiki[:version]} of trac-file #{wiki[:name]}"
|
42
|
+
else
|
43
|
+
wiki[:comment].gsub('"', '\"')
|
44
|
+
end
|
45
|
+
|
46
|
+
file_name = "#{cleanse_filename(wiki[:name])}.md"
|
47
|
+
$logger.info("Working with file [#{file_name}]")
|
48
|
+
$logger.debug("Object: #{wiki}")
|
49
|
+
|
50
|
+
wiki_markdown_text = @twf_to_markdown.convert(wiki[:text])
|
51
|
+
wiki_markdown_text += wiki_attachments(wiki)
|
52
|
+
|
53
|
+
# Create file with content
|
54
|
+
File.open(file_name, "w") do |f|
|
55
|
+
f.puts(wiki_markdown_text)
|
56
|
+
end
|
57
|
+
|
58
|
+
# git-add it
|
59
|
+
unless execute_command("git add #{file_name}").success?
|
60
|
+
$logger.error("ERROR at git-add #{file_name}!!!")
|
61
|
+
exit(1)
|
62
|
+
end
|
63
|
+
|
64
|
+
author = generate_author(wiki[:author])
|
65
|
+
|
66
|
+
# git-commit it
|
67
|
+
commit_command = "git commit --allow-empty -m \"#{comment}\" --author \"#{author}\" --date \"#{wiki[:fixeddate]}\""
|
68
|
+
unless execute_command(commit_command).success?
|
69
|
+
$logger.error("ERROR at git-commit #{file_name}!!!")
|
70
|
+
exit(1)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def verify_options
|
79
|
+
$logger.info("Verifying options...")
|
80
|
+
|
81
|
+
missing_options = []
|
82
|
+
missing_options << "attachment-base-url" if @wiki_attachments_url.empty?
|
83
|
+
missing_options << "repo-path" if @repo_path.empty?
|
84
|
+
|
85
|
+
return if missing_options.empty?
|
86
|
+
|
87
|
+
$logger.error("Following options are missing: #{missing_options} - exiting...")
|
88
|
+
exit(1)
|
89
|
+
end
|
90
|
+
|
91
|
+
def verify_locations
|
92
|
+
$logger.info("Verifying locations...")
|
93
|
+
missing_directories = []
|
94
|
+
|
95
|
+
# git-root exists?
|
96
|
+
missing_directories << "repo-path" unless Dir.exist?(@repo_path)
|
97
|
+
|
98
|
+
return if missing_directories.empty?
|
99
|
+
|
100
|
+
$logger.error("Following directories are missing: #{missing_directories} - exiting ...")
|
101
|
+
exit(1)
|
102
|
+
end
|
103
|
+
|
104
|
+
def cleanse_filename(name)
|
105
|
+
# Get rid of 'magic' characters from potential filename - replace with '_'
|
106
|
+
# Magic: [ /<>- ]
|
107
|
+
name.gsub(%r{[/<>-]}, "_")
|
108
|
+
end
|
109
|
+
|
110
|
+
def skip_file(file_name)
|
111
|
+
file_name.start_with?("Trac") || (file_name.start_with?("Wiki") && !file_name.start_with?("WikiStart"))
|
112
|
+
end
|
113
|
+
|
114
|
+
def generate_author(author)
|
115
|
+
return "" if author.nil? || author.empty?
|
116
|
+
|
117
|
+
author_name = @authors_map[author]&.[]("name") || author.split("@").first
|
118
|
+
author_email = @authors_map[author]&.[]("email") || author
|
119
|
+
|
120
|
+
"#{author_name} <#{author_email}>"
|
121
|
+
end
|
122
|
+
|
123
|
+
def wiki_attachments(wiki)
|
124
|
+
attachments = wiki.attachments
|
125
|
+
return "" if attachments.count.zero?
|
126
|
+
|
127
|
+
attachments_list = ["# Attachments\n"]
|
128
|
+
|
129
|
+
attachments.each do |attachment|
|
130
|
+
attachment_path = Tractive::Utilities.attachment_path(
|
131
|
+
wiki.name, attachment.filename, hashed: @attachments_hashed
|
132
|
+
)
|
133
|
+
attachments_list << "- [#{attachment.filename}](#{@wiki_attachments_url}/#{attachment_path})"
|
134
|
+
end
|
135
|
+
|
136
|
+
attachments_list.join("\n")
|
137
|
+
end
|
138
|
+
|
139
|
+
def execute_command(command)
|
140
|
+
`#{command}`
|
141
|
+
$CHILD_STATUS
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/lib/tractive/migrator.rb
CHANGED
@@ -19,14 +19,18 @@ module Tractive
|
|
19
19
|
def filter_column(options)
|
20
20
|
return self if options.nil? || options.values.compact.empty?
|
21
21
|
|
22
|
-
case options[:operator].downcase
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
query = case options[:operator].downcase
|
23
|
+
when "like"
|
24
|
+
Sequel.like(options[:column_name].to_sym, options[:column_value])
|
25
|
+
when "not like"
|
26
|
+
~Sequel.like(options[:column_name].to_sym, options[:column_value])
|
27
|
+
else
|
28
|
+
Sequel.lit("#{options[:column_name]} #{options[:operator]} '#{options[:column_value]}'")
|
29
|
+
end
|
30
|
+
|
31
|
+
query = Sequel.|(query, { options[:column_name].to_sym => nil }) if options[:include_null]
|
32
|
+
|
33
|
+
where { query }
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
@@ -35,5 +39,9 @@ module Tractive
|
|
35
39
|
change_arr = changes + attachments
|
36
40
|
change_arr.sort_by { |change| change[:time] }
|
37
41
|
end
|
42
|
+
|
43
|
+
def closed_comments
|
44
|
+
changes_dataset.where(field: "status", newvalue: "closed")
|
45
|
+
end
|
38
46
|
end
|
39
47
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tractive
|
4
|
+
class Wiki < Sequel::Model(:wiki)
|
5
|
+
set_primary_key :name
|
6
|
+
one_to_many :attachments, class: Attachment, key: :id, conditions: { type: "wiki" }
|
7
|
+
|
8
|
+
dataset_module do
|
9
|
+
def for_migration
|
10
|
+
select(:name, :version, :author, :comment, Sequel.lit("datetime(time/1000000, 'unixepoch')").as(:fixeddate), :text).order(:name, :version)
|
11
|
+
end
|
12
|
+
|
13
|
+
def latest_versions
|
14
|
+
select(:name, :version, :text).group(:name).having { version =~ MAX(version) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/tractive/trac.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Tractive
|
4
4
|
class Trac
|
5
|
-
attr_reader :tickets, :changes, :sessions, :attachments
|
5
|
+
attr_reader :tickets, :changes, :sessions, :attachments, :wikis
|
6
6
|
|
7
7
|
def initialize(db)
|
8
8
|
$logger.info("loading tickets")
|
@@ -11,6 +11,7 @@ module Tractive
|
|
11
11
|
@changes = TicketChange
|
12
12
|
@sessions = Session
|
13
13
|
@attachments = Attachment
|
14
|
+
@wikis = Wiki
|
14
15
|
end
|
15
16
|
end
|
16
17
|
end
|
data/lib/tractive/utilities.rb
CHANGED
@@ -22,7 +22,8 @@ module Tractive
|
|
22
22
|
"lib/tractive/models/revision.rb",
|
23
23
|
"lib/tractive/models/session.rb",
|
24
24
|
"lib/tractive/models/ticket_change.rb",
|
25
|
-
"lib/tractive/models/ticket.rb"
|
25
|
+
"lib/tractive/models/ticket.rb",
|
26
|
+
"lib/tractive/models/wiki.rb"
|
26
27
|
]
|
27
28
|
db = Sequel.connect(db_url) if db_url
|
28
29
|
|
@@ -35,6 +36,17 @@ module Tractive
|
|
35
36
|
db
|
36
37
|
end
|
37
38
|
|
39
|
+
def attachment_path(id, filename, options = {})
|
40
|
+
return "#{id}/#{filename}" unless options[:hashed]
|
41
|
+
|
42
|
+
folder_name = Digest::SHA1.hexdigest(id)
|
43
|
+
parent_folder_name = folder_name[0..2]
|
44
|
+
hashed_filename = Digest::SHA1.hexdigest(filename)
|
45
|
+
file_extension = File.extname(filename)
|
46
|
+
|
47
|
+
"#{parent_folder_name}/#{folder_name}/#{hashed_filename}#{file_extension}"
|
48
|
+
end
|
49
|
+
|
38
50
|
def setup_logger(options = {})
|
39
51
|
$logger = Logger.new(options[:output_stream])
|
40
52
|
$logger.level = options[:verbose] ? Logger::DEBUG : Logger::INFO
|
@@ -46,7 +58,7 @@ module Tractive
|
|
46
58
|
|
47
59
|
# returns the git commit hash for a specified revision (using revmap hash)
|
48
60
|
def map_changeset(str, revmap, changeset_base_url = "")
|
49
|
-
if revmap&.key?(str)
|
61
|
+
if revmap&.key?(str) && !revmap[str].nil?
|
50
62
|
base_url = changeset_base_url
|
51
63
|
base_url += "/" if base_url[-1] && base_url[-1] != "/"
|
52
64
|
"#{base_url}#{revmap[str].strip}"
|
data/lib/tractive/version.rb
CHANGED
data/lib/tractive.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.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mysql2
|
@@ -112,6 +112,8 @@ description:
|
|
112
112
|
email:
|
113
113
|
- open.source@ribose.com
|
114
114
|
executables:
|
115
|
+
- command_base.rb
|
116
|
+
- generate.rb
|
115
117
|
- tractive
|
116
118
|
extensions: []
|
117
119
|
extra_rdoc_files: []
|
@@ -133,6 +135,8 @@ files:
|
|
133
135
|
- db/trac-test.db
|
134
136
|
- docker/Dockerfile
|
135
137
|
- docker/docker-compose.yml
|
138
|
+
- exe/command_base.rb
|
139
|
+
- exe/generate.rb
|
136
140
|
- exe/tractive
|
137
141
|
- lib/tractive.rb
|
138
142
|
- lib/tractive/attachment_exporter.rb
|
@@ -142,6 +146,8 @@ files:
|
|
142
146
|
- lib/tractive/github_api/client/labels.rb
|
143
147
|
- lib/tractive/github_api/client/milestones.rb
|
144
148
|
- lib/tractive/graceful_quit.rb
|
149
|
+
- lib/tractive/http/client.rb
|
150
|
+
- lib/tractive/http/client/request.rb
|
145
151
|
- lib/tractive/info.rb
|
146
152
|
- lib/tractive/main.rb
|
147
153
|
- lib/tractive/migrator.rb
|
@@ -152,6 +158,8 @@ files:
|
|
152
158
|
- lib/tractive/migrator/engine/migrate_from_db.rb
|
153
159
|
- lib/tractive/migrator/engine/migrate_from_file.rb
|
154
160
|
- lib/tractive/migrator/engine/migrate_to_file.rb
|
161
|
+
- lib/tractive/migrator/wikis.rb
|
162
|
+
- lib/tractive/migrator/wikis/migrate_from_db.rb
|
155
163
|
- lib/tractive/models/attachment.rb
|
156
164
|
- lib/tractive/models/milestone.rb
|
157
165
|
- lib/tractive/models/report.rb
|
@@ -159,6 +167,7 @@ files:
|
|
159
167
|
- lib/tractive/models/session.rb
|
160
168
|
- lib/tractive/models/ticket.rb
|
161
169
|
- lib/tractive/models/ticket_change.rb
|
170
|
+
- lib/tractive/models/wiki.rb
|
162
171
|
- lib/tractive/revmap_generator.rb
|
163
172
|
- lib/tractive/trac.rb
|
164
173
|
- lib/tractive/utilities.rb
|