--- a/trac/project.go Tue Aug 11 22:10:48 2020 -0500
+++ b/trac/project.go Tue Aug 11 23:04:40 2020 -0500
@@ -6,7 +6,7 @@
"keep.imfreedom.org/grim/youtrack-import/youtrack"
-func createProject(e *environment, importUsersFile, unknownUser string) (*youtrack.Project, error) {
+func createProject(projectID string, e *environment, importUsersFile, unknownUser string) (*youtrack.Project, error) { users, err := e.loadUsers(importUsersFile)
@@ -26,7 +26,7 @@
fmt.Printf("loaded %d subsystems\n", len(ytSubsystems))
- ytIssues, err := e.loadTickets(users, unknownUser)
+ ytIssues, err := e.loadTickets(projectID, users, unknownUser) --- a/trac/tickets.go Tue Aug 11 22:10:48 2020 -0500
+++ b/trac/tickets.go Tue Aug 11 23:04:40 2020 -0500
@@ -114,9 +114,12 @@
boldItalicRegex = regexp.MustCompile(`'''''(.+?)'''''`)
boldRegex = regexp.MustCompile(`'''(.+?)'''`)
italicRegex = regexp.MustCompile(`''(.+?)''`)
+ ticketLinkRegex = regexp.MustCompile(`#(\d+)([^\w])`) -func convertComment(comment string) string {
+func convertComment(projectID, comment string) string { if strings.Contains(comment, "{{{") {
// inline code uses the same syntax so we need to do code blocks
@@ -134,23 +137,26 @@
// replace italic with 1 *'s because that's italic in markdown...
comment = italicRegex.ReplaceAllString(comment, "*$1*")
+ // replace any ticket link references + comment = ticketLinkRegex.ReplaceAllString(comment, projectID+"-$1$2") -func (tc *ticketChange) cleanNewValue() string {
+func (tc *ticketChange) cleanNewValue(projectID string) string { if tc.Field == "comment" {
newComment := convertString(tc.NewValue)
if strings.Contains(convertString(tc.OldValue), ".") {
newComment = commentReplyingRegex.ReplaceAllString(newComment, "")
- return convertComment(newComment)
+ return convertComment(projectID, newComment) return tc.NewValue.String
-func (t *ticket) toYoutrack(users map[string]*youtrack.User, unknownUser string) (*youtrack.Issue, error) {
+func (t *ticket) toYoutrack(projectID string, users map[string]*youtrack.User, unknownUser string) (*youtrack.Issue, error) { convertUsername := func(sqluser sql.NullString) string {
username := convertString(sqluser)
return mapUser(username, unknownUser, users)
@@ -180,7 +186,7 @@
issue := &youtrack.Issue{
- Description: convertComment(t.Description),
+ Description: convertComment(projectID, t.Description), Created: convertTime(t.Time),
Updated: convertTime(t.ChangeTime),
Reporter: convertUsername(t.Reporter),
@@ -243,7 +249,7 @@
- description = change.cleanNewValue()
+ description = change.cleanNewValue(projectID) issue.UpdatedBy = convertUsername(change.Author)
@@ -326,7 +332,7 @@
-func (e *environment) loadTickets(users map[string]*youtrack.User, unknownUser string) ([]*youtrack.Issue, error) {
+func (e *environment) loadTickets(projectID string, users map[string]*youtrack.User, unknownUser string) ([]*youtrack.Issue, error) { @@ -364,7 +370,7 @@
issues := make([]*youtrack.Issue, len(tickets))
for idx, ticket := range tickets {
- issue, err := ticket.toYoutrack(users, unknownUser)
+ issue, err := ticket.toYoutrack(projectID, users, unknownUser)