grim/youtrack-import
Fix up the version and subsystem code to handle additional fields
--- a/bitbucket/converter.go Fri Jul 03 22:56:34 2020 -0500
+++ b/bitbucket/converter.go Tue Jul 07 23:42:04 2020 -0500
@@ -204,15 +204,15 @@
// create a string slice of all the components
- components := make([]string, len(a.Components))
+ components := make([]youtrack.OwnedField, len(a.Components)) for i := 0; i < len(a.Components); i++ {
- components[i] = a.Components[i].Name
+ components[i] = youtrack.OwnedField{Value: a.Components[i].Name} // create a string slice of all the versions
- versions := make([]string, len(a.Versions))
+ versions := make([]youtrack.Version, len(a.Versions)) for i := 0; i < len(a.Versions); i++ {
- versions[i] = a.Versions[i].Name
+ versions[i] = youtrack.Version{Name: a.Versions[i].Name} // convert all of the issues
--- a/build-and-run Fri Jul 03 22:56:34 2020 -0500
+++ b/build-and-run Tue Jul 07 23:42:04 2020 -0500
@@ -4,5 +4,5 @@
echo -n "deleting project \"${1}\" ... "
curl -X DELETE -H "Authorization: Bearer ${YOUTRACK_TOKEN}" "${YOUTRACK_URL}rest/admin/project/${1}"
-./youtrack-import --project-id="${1}" --project-name="${2}" bitbucket "${3}" "${4}" "${5}"
+./youtrack-import --project-id="${1}" --project-name="${2}" trac "${3}" "--import-users=${4}" --- a/trac/components.go Fri Jul 03 22:56:34 2020 -0500
+++ b/trac/components.go Tue Jul 07 23:42:04 2020 -0500
@@ -1,13 +1,38 @@
+ "keep.imfreedom.org/grim/youtrack-import/youtrack" -func (e *environment) loadComponents() ([]string, error) {
- components := []string{}
+ Name string `db:"name"` + Owner sql.NullString `db:"owner"` + Description sql.NullString `db:"description"` +func (e *environment) loadComponents() ([]component, error) { + components := []component{} - "SELECT distinct(component) from ticket ORDER BY component ASC",
+ distinct(t.component) AS name, + c.description AS description + FULL JOIN trac_pidgin.ticket t ON +func (c *component) toYouTrack() youtrack.OwnedField { + return youtrack.OwnedField{ + Description: convertString(c.Description), + Owner: convertString(c.Owner), --- a/trac/project.go Fri Jul 03 22:56:34 2020 -0500
+++ b/trac/project.go Tue Jul 07 23:42:04 2020 -0500
@@ -14,10 +14,23 @@
fmt.Printf("loaded %d users\n", len(users))
+ versions, err := e.loadVersions() + ytVersions := make([]youtrack.Version, len(versions)) + for idx, version := range versions { + ytVersions[idx] = version.toYouTrack() components, err := e.loadComponents()
+ ytSubsystems := make([]youtrack.OwnedField, len(components)) + for idx, component := range components { + ytSubsystems[idx] = component.toYouTrack() tracTickets, err := e.loadTickets()
@@ -44,7 +57,8 @@
project := &youtrack.Project{
- Subsystems: components,
+ Subsystems: ytSubsystems, fmt.Printf("Project: has %d issues\n", len(issues))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/trac/versions.go Tue Jul 07 23:42:04 2020 -0500
@@ -0,0 +1,37 @@
+ "keep.imfreedom.org/grim/youtrack-import/youtrack" + Name string `db:"name"` + Description sql.NullString `db:"description"` +func (e *environment) loadVersions() ([]version, error) { + versions := []version{} + "SELECT * from version ORDER BY name DESC", +func (v *version) toYouTrack() youtrack.Version { + ytVersion := youtrack.Version{ + Description: convertString(v.Description), + ytVersion.Released = true + ytVersion.ReleaseDate = convertTime(v.Time) --- a/youtrack/import.go Fri Jul 03 22:56:34 2020 -0500
+++ b/youtrack/import.go Tue Jul 07 23:42:04 2020 -0500
@@ -31,6 +31,11 @@
+ if err := client.ImportUsers(p); err != nil { if err := client.CreateSubsystems(p); err != nil {
@@ -41,11 +46,6 @@
- if err := client.ImportUsers(p); err != nil {
if err := client.ImportIssues(p); err != nil {
--- a/youtrack/ownedfield.go Fri Jul 03 22:56:34 2020 -0500
+++ b/youtrack/ownedfield.go Tue Jul 07 23:42:04 2020 -0500
@@ -4,6 +4,7 @@
@@ -39,10 +40,20 @@
return bundle, xml.NewDecoder(resp.Body).Decode(bundle)
-func (c *Client) AppendOwnedFieldBundle(name, value string) error {
+func (c *Client) AppendOwnedFieldBundle(name string, field OwnedField) error { + baseUri := c.uri + "/admin/customfield/ownedFieldBundle/" + name + "/" + field.Value + if field.Description != "" { + values.Add("description", field.Description) + values.Add("login", field.Owner) - c.uri+"/admin/customfield/ownedFieldBundle/"+name+"/"+value,
+ baseUri+"?"+values.Encode(), @@ -52,7 +63,7 @@
if err := c.checkStatus(resp, http.StatusCreated); err != nil {
- return fmt.Errorf("failed to append %q to %q: %s", value, name, err)
+ return fmt.Errorf("failed to append %q to %q: %s", field.Value, name, err) --- a/youtrack/project.go Fri Jul 03 22:56:34 2020 -0500
+++ b/youtrack/project.go Tue Jul 07 23:42:04 2020 -0500
@@ -11,8 +11,8 @@
+ Subsystems []OwnedField --- a/youtrack/subsystems.go Fri Jul 03 22:56:34 2020 -0500
+++ b/youtrack/subsystems.go Tue Jul 07 23:42:04 2020 -0500
@@ -32,9 +32,9 @@
// now run through the map and add the new values
for _, subsystem := range p.Subsystems {
- fmt.Printf("creating subsystem %q ... ", subsystem)
+ fmt.Printf("creating subsystem %q ... ", subsystem.Value) - if _, found := existing[subsystem]; found {
+ if _, found := existing[subsystem.Value]; found { fmt.Printf("already exists.\n")
--- a/youtrack/version.go Fri Jul 03 22:56:34 2020 -0500
+++ b/youtrack/version.go Tue Jul 07 23:42:04 2020 -0500
@@ -4,8 +4,20 @@
type VersionField struct {
Released bool `xml:"released,attr"`
Archived bool `xml:"archived,attr"`
@@ -55,10 +67,27 @@
return bundle, xml.NewDecoder(resp.Body).Decode(bundle)
-func (c *Client) AppendVersionFieldBundle(name, value string) error {
+func (c *Client) AppendVersionFieldBundle(name string, version Version) error { + baseUri := c.uri + "/admin/customfield/versionBundle/" + name + "/" + version.Name + if version.Description != "" { + values.Add("description", version.Description) + if version.Released != false { + values.Add("released", "true") + if !version.ReleaseDate.IsZero() { + values.Add("releaseDate", fmt.Sprintf("%d", version.ReleaseDate.Unix()*1000)) + if version.Archived != false { + values.Add("archived", "true") - c.uri+"/admin/customfield/versionBundle/"+name+"/"+value,
+ baseUri+"?"+values.Encode(), @@ -68,7 +97,7 @@
if err := c.checkStatus(resp, http.StatusCreated); err != nil {
- return fmt.Errorf("failed to append %q to %q: %v", value, name, err)
+ return fmt.Errorf("failed to append %q to %q: %v", version.Name, name, err) @@ -88,9 +117,9 @@
// now run through the version slice and add all the versions
for _, version := range p.Versions {
- fmt.Printf("creating version %q ... ", version)
+ fmt.Printf("creating version %q ... ", version.Name) - if _, found := existing[version]; found {
+ if _, found := existing[version.Name]; found { fmt.Printf("already exists.\n")