grim/youtrack-import
Clone
Summary
Browse
Changes
Graph
replace [[br]] from trac with <br/>. Fixed YI-33
draft
2020-08-03, Gary Kramlich
6e41a2be36b1
replace [[br]] from trac with
. Fixed YI-33
package
bitbucket
import
(
"fmt"
"regexp"
"strings"
"keep.imfreedom.org/grim/youtrack-import/youtrack"
)
var
(
kindMap
=
map
[
string
]
string
{
"bug"
:
"Bug"
,
"enhancement"
:
"Feature"
,
"proposal"
:
"Feature"
,
"task"
:
"Task"
,
}
statusMap
=
map
[
string
]
string
{
"new"
:
"Submitted"
,
"open"
:
"Open"
,
"resolved"
:
"Fixed"
,
"on hold"
:
"Incomplete"
,
"invalid"
:
"Can't Reproduce"
,
"duplicate"
:
"Duplicate"
,
"wontfix"
:
"Won't Fix"
,
"closed"
:
"Fixed"
,
}
priorityMap
=
map
[
string
]
string
{
"trivial"
:
"Minor"
,
"minor"
:
"Normal"
,
"major"
:
"Major"
,
"critical"
:
"Critical"
,
"blocker"
:
"Show-stopper"
,
}
newlineRegex
=
regexp
.
MustCompile
(
`\r\n`
)
)
func
cleanupMessage
(
m
map
[
string
]
*
youtrack
.
User
,
nIssues
int
,
projectID
,
repository
,
message
string
)
string
{
output
:=
message
// replace \r\n with \n
output
=
newlineRegex
.
ReplaceAllString
(
output
,
"\n"
)
output
=
replaceKeywords
(
m
,
nIssues
,
projectID
,
repository
,
output
)
output
=
replaceCreole
(
m
,
output
)
return
output
}
func
(
a
*
Archive
)
convertIssue
(
nIssues
int
,
projectID
,
repository
string
,
bb
Issue
,
userMap
map
[
string
]
*
youtrack
.
User
)
*
youtrack
.
Issue
{
reporter
:=
"admin"
if
user
,
found
:=
userMap
[
bb
.
Reporter
.
AccountID
];
found
{
reporter
=
user
.
Login
}
assignee
:=
""
if
user
,
found
:=
userMap
[
bb
.
Assignee
.
AccountID
];
found
{
assignee
=
user
.
Login
}
yt
:=
&
youtrack
.
Issue
{
Number
:
bb
.
ID
,
Summary
:
bb
.
Title
,
Description
:
cleanupMessage
(
userMap
,
nIssues
,
projectID
,
repository
,
bb
.
Content
),
Created
:
bb
.
CreatedOn
,
Updated
:
bb
.
UpdatedOn
,
Reporter
:
reporter
,
Assignee
:
assignee
,
Priority
:
bb
.
Priority
,
Type
:
bb
.
Kind
,
State
:
bb
.
Status
,
Version
:
bb
.
Version
,
Subsystem
:
bb
.
Component
,
Markdown
:
true
,
Comments
:
[]
*
youtrack
.
Comment
{},
}
yt
.
Voters
=
flattenAuthors
(
userMap
,
bb
.
Voters
)
yt
.
Watchers
=
flattenAuthors
(
userMap
,
bb
.
Watchers
)
// map field values from bitbucket to youtrack
if
replace
,
found
:=
priorityMap
[
yt
.
Priority
];
found
{
yt
.
Priority
=
replace
}
if
replace
,
found
:=
kindMap
[
yt
.
Type
];
found
{
yt
.
Type
=
replace
}
if
replace
,
found
:=
statusMap
[
yt
.
State
];
found
{
yt
.
State
=
replace
}
// add the comments and attachments
yt
.
Comments
=
a
.
convertComments
(
nIssues
,
projectID
,
repository
,
userMap
,
bb
.
ID
)
yt
.
Attachments
=
a
.
convertAttachments
(
userMap
,
bb
)
return
yt
}
func
(
a
*
Archive
)
convertComments
(
nIssues
int
,
projectID
,
repository
string
,
userMap
map
[
string
]
*
youtrack
.
User
,
id
int
)
[]
*
youtrack
.
Comment
{
comments
:=
[]
*
youtrack
.
Comment
{}
for
_
,
comment
:=
range
a
.
Comments
{
if
comment
.
Issue
!=
id
{
continue
}
// check if there were any stage changes with this comment
stateChanges
:=
[]
string
{}
for
_
,
log
:=
range
a
.
Logs
{
if
log
.
Comment
==
comment
.
ID
{
if
log
.
Field
==
"content"
{
stateChanges
=
append
(
stateChanges
,
"* **edited description**"
)
}
else
{
from
:=
log
.
ChangedFrom
if
from
==
""
{
from
=
"*unset*"
}
to
:=
log
.
ChangedTo
if
to
==
""
{
to
=
"*unset*"
}
change
:=
fmt
.
Sprintf
(
"* **%s**: %s ⟶ %s"
,
log
.
Field
,
from
,
to
,
)
stateChanges
=
append
(
stateChanges
,
change
)
}
}
}
if
logContent
:=
strings
.
Join
(
stateChanges
,
"\n"
);
logContent
!=
""
{
comment
.
Content
=
logContent
+
"\n\n"
+
comment
.
Content
}
author
:=
"admin"
if
user
,
found
:=
userMap
[
comment
.
User
.
AccountID
];
found
{
author
=
user
.
Login
}
ytComment
:=
&
youtrack
.
Comment
{
Author
:
author
,
Text
:
cleanupMessage
(
userMap
,
nIssues
,
projectID
,
repository
,
comment
.
Content
),
Created
:
comment
.
CreatedOn
,
Updated
:
comment
.
UpdatedOn
,
Markdown
:
true
,
}
comments
=
append
(
comments
,
ytComment
)
}
return
comments
}
func
(
a
*
Archive
)
convertAttachments
(
userMap
map
[
string
]
*
youtrack
.
User
,
issue
Issue
)
[]
*
youtrack
.
Attachment
{
attachments
:=
[]
*
youtrack
.
Attachment
{}
for
_
,
attachment
:=
range
a
.
Attachments
{
if
attachment
.
Issue
!=
issue
.
ID
{
continue
}
author
:=
"admin"
if
user
,
found
:=
userMap
[
attachment
.
User
.
AccountID
];
found
{
author
=
user
.
Login
}
reader
,
err
:=
a
.
OpenAttachment
(
attachment
.
Path
)
if
err
!=
nil
{
fmt
.
Printf
(
"%v\n"
,
err
)
continue
}
yt
:=
youtrack
.
NewAttachment
(
attachment
.
Issue
,
author
,
issue
.
CreatedOn
)
yt
.
AddFile
(
reader
,
attachment
.
Filename
)
attachments
=
append
(
attachments
,
yt
)
}
return
attachments
}
func
(
a
*
Archive
)
convert
(
projectID
,
repository
string
,
usersMap
*
UsersMap
)
(
*
youtrack
.
Project
,
error
)
{
users
,
err
:=
a
.
ExtractUsers
(
usersMap
)
if
err
!=
nil
{
return
nil
,
err
}
// create a slice of youtrack users for import
ytUsers
:=
make
([]
*
youtrack
.
User
,
len
(
users
))
i
:=
0
for
_
,
user
:=
range
users
{
ytUsers
[
i
]
=
user
i
++
}
// create a string slice of all the components
components
:=
make
([]
youtrack
.
OwnedField
,
len
(
a
.
Components
))
for
i
:=
0
;
i
<
len
(
a
.
Components
);
i
++
{
components
[
i
]
=
youtrack
.
OwnedField
{
Value
:
a
.
Components
[
i
].
Name
}
}
// create a string slice of all the versions
versions
:=
make
([]
youtrack
.
Version
,
len
(
a
.
Versions
))
for
i
:=
0
;
i
<
len
(
a
.
Versions
);
i
++
{
versions
[
i
]
=
youtrack
.
Version
{
Name
:
a
.
Versions
[
i
].
Name
}
}
// convert all of the issues
nIssues
:=
len
(
a
.
Issues
)
issues
:=
make
([]
*
youtrack
.
Issue
,
nIssues
)
for
i
:=
0
;
i
<
nIssues
;
i
++
{
issues
[
i
]
=
a
.
convertIssue
(
nIssues
,
projectID
,
repository
,
a
.
Issues
[
i
],
users
)
}
project
:=
&
youtrack
.
Project
{
Users
:
ytUsers
,
Subsystems
:
components
,
Versions
:
versions
,
Issues
:
issues
,
}
return
project
,
nil
}