@@ -4,6 +4,8 @@ import * as utils from './utils';
4
4
import { Octokit as GitHubApi , RestEndpointMethodTypes } from '@octokit/rest' ;
5
5
import { Endpoints } from '@octokit/types' ;
6
6
import {
7
+ GitLabDiscussion ,
8
+ GitLabDiscussionNote ,
7
9
GitlabHelper ,
8
10
GitLabIssue ,
9
11
GitLabMergeRequest ,
@@ -561,6 +563,85 @@ export class GithubHelper {
561
563
) ;
562
564
return comments ;
563
565
}
566
+
567
+ /**
568
+ *
569
+ * @param discussions
570
+ * @returns Comments ready for requestImportIssue()
571
+ */
572
+ async processDiscussionsIntoComments (
573
+ discussions : GitLabDiscussion [ ]
574
+ ) : Promise < CommentImport [ ] > {
575
+ if ( ! discussions || ! discussions . length ) {
576
+ console . log ( `\t...no comments available, nothing to migrate.` ) ;
577
+ return [ ] ;
578
+ }
579
+
580
+ let comments : CommentImport [ ] = [ ] ;
581
+
582
+ // sort notes in ascending order of when they were created (by id)
583
+ discussions = discussions . sort ( ( a , b ) => Number . parseInt ( a . id ) - Number . parseInt ( b . id ) ) ;
584
+
585
+ let nrOfMigratedNotes = 0 ;
586
+ let nrOfSkippedNotes = 0 ;
587
+ for ( let discussion of discussions ) {
588
+ let discussionComments = [ ] ;
589
+
590
+ for ( let note of discussion . notes ) {
591
+ if ( this . checkIfNoteCanBeSkipped ( note . body ) ) {
592
+ nrOfSkippedNotes ++ ;
593
+ continue ;
594
+ }
595
+
596
+ let username = note . author . username as string ;
597
+ this . users . add ( username ) ;
598
+ let userIsPoster =
599
+ ( settings . usermap &&
600
+ settings . usermap [ username ] ===
601
+ settings . github . token_owner ) ||
602
+ username === settings . github . token_owner ;
603
+
604
+ // only add line ref for first note of discussion
605
+ const add_line_ref = discussion . notes . indexOf ( note ) === 0 ;
606
+
607
+ discussionComments . push ( {
608
+ created_at : note . created_at ,
609
+ body : await this . convertIssuesAndComments (
610
+ note . body ,
611
+ note ,
612
+ ! userIsPoster || ! note . body ,
613
+ add_line_ref ,
614
+ ) ,
615
+ } ) ;
616
+
617
+ nrOfMigratedNotes ++ ;
618
+ }
619
+
620
+ // Combine notes for discussion into one comment
621
+ if ( discussionComments . length == 1 ) {
622
+ comments . push ( discussionComments [ 0 ] ) ;
623
+ }
624
+ else if ( discussionComments . length > 1 ) {
625
+ let combinedBody = '**Discussion in GitLab:**\n\n' ;
626
+ let first_created_at = discussionComments [ 0 ] . created_at ;
627
+
628
+ combinedBody += discussionComments . map ( comment => comment . body ) . join ( '\n\n' ) ;
629
+
630
+ comments . push ( {
631
+ created_at : first_created_at ,
632
+ body : combinedBody ,
633
+ } ) ;
634
+ }
635
+ }
636
+
637
+ console . log (
638
+ `\t...Done creating discussion comments (migrated ${ nrOfMigratedNotes } comments, skipped ${
639
+ nrOfSkippedNotes
640
+ } comments)`
641
+ ) ;
642
+ return comments ;
643
+ }
644
+
564
645
/**
565
646
* Calls the preview API for issue importing
566
647
*
@@ -691,7 +772,7 @@ export class GithubHelper {
691
772
* Return false when it got skipped, otherwise true.
692
773
*/
693
774
async processNote (
694
- note : GitLabNote ,
775
+ note : GitLabNote | GitLabDiscussionNote ,
695
776
githubIssue : Pick < GitHubIssue | GitHubPullRequest , 'number' >
696
777
) {
697
778
if ( this . checkIfNoteCanBeSkipped ( note . body ) ) return false ;
@@ -966,10 +1047,10 @@ export class GithubHelper {
966
1047
'\t...this is a placeholder for a deleted GitLab merge request, no comments are created.'
967
1048
) ;
968
1049
} else {
969
- let notes = await this . gitlabHelper . getAllMergeRequestNotes (
1050
+ let discussions = await this . gitlabHelper . getAllMergeRequestDiscussions (
970
1051
mergeRequest . iid
971
1052
) ;
972
- comments = await this . processNotesIntoComments ( notes ) ;
1053
+ comments = await this . processDiscussionsIntoComments ( discussions ) ;
973
1054
}
974
1055
975
1056
return this . requestImportIssue ( props , comments ) ;
@@ -1010,30 +1091,72 @@ export class GithubHelper {
1010
1091
return Promise . resolve ( ) ;
1011
1092
}
1012
1093
1013
- let notes = await this . gitlabHelper . getAllMergeRequestNotes (
1094
+ let discussions = await this . gitlabHelper . getAllMergeRequestDiscussions (
1014
1095
mergeRequest . iid
1015
1096
) ;
1016
1097
1017
1098
// if there are no notes, then there is nothing to do!
1018
- if ( notes . length === 0 ) {
1099
+ if ( discussions . length === 0 ) {
1019
1100
console . log (
1020
1101
`\t...no pull request comments available, nothing to migrate.`
1021
1102
) ;
1022
1103
return ;
1023
1104
}
1024
1105
1025
1106
// Sort notes in ascending order of when they were created (by id)
1026
- notes = notes . sort ( ( a , b ) => a . id - b . id ) ;
1107
+ discussions = discussions . sort ( ( a , b ) => a . notes [ 0 ] . id - b . notes [ 0 ] . id ) ;
1027
1108
1028
1109
let nrOfMigratedNotes = 0 ;
1029
- for ( let note of notes ) {
1030
- const gotMigrated = await this . processNote ( note , pullRequest ) ;
1031
- if ( gotMigrated ) nrOfMigratedNotes ++ ;
1110
+ let nrOfSkippedNotes = 0 ;
1111
+ for ( let discussion of discussions ) {
1112
+ if ( discussion . individual_note ) {
1113
+ const gotMigrated = await this . processNote ( discussion . notes [ 0 ] , pullRequest ) ;
1114
+ if ( gotMigrated ) {
1115
+ nrOfMigratedNotes ++ ;
1116
+ }
1117
+ else {
1118
+ nrOfSkippedNotes ++ ;
1119
+ }
1120
+ }
1121
+ else {
1122
+ // console.log('Processing discussion:');
1123
+ let discussionBody = '**Discussion in GitLab:**\n\n' ;
1124
+
1125
+ for ( let note of discussion . notes ) {
1126
+ if ( this . checkIfNoteCanBeSkipped ( note . body ) ) {
1127
+ nrOfSkippedNotes ++ ;
1128
+ continue ;
1129
+ }
1130
+
1131
+ const add_line_ref = discussion . notes . indexOf ( note ) === 0 ;
1132
+ let bodyConverted = await this . convertIssuesAndComments ( note . body , note , true , add_line_ref ) ;
1133
+ discussionBody += bodyConverted ;
1134
+ discussionBody += '\n\n' ;
1135
+ nrOfMigratedNotes ++ ;
1136
+ }
1137
+
1138
+ await utils . sleep ( this . delayInMs ) ;
1139
+
1140
+ if ( ! settings . dryRun ) {
1141
+ await this . githubApi . issues
1142
+ . createComment ( {
1143
+ owner : this . githubOwner ,
1144
+ repo : this . githubRepo ,
1145
+ issue_number : pullRequest . number ,
1146
+ body : discussionBody ,
1147
+ } )
1148
+ . catch ( x => {
1149
+ console . error ( 'could not create GitHub issue comment!' ) ;
1150
+ console . error ( x ) ;
1151
+ process . exit ( 1 ) ;
1152
+ } ) ;
1153
+ }
1154
+ }
1032
1155
}
1033
1156
1034
1157
console . log (
1035
1158
`\t...Done creating pull request comments (migrated ${ nrOfMigratedNotes } pull request comments, skipped ${
1036
- notes . length - nrOfMigratedNotes
1159
+ nrOfSkippedNotes
1037
1160
} pull request comments)`
1038
1161
) ;
1039
1162
}
@@ -1159,8 +1282,9 @@ export class GithubHelper {
1159
1282
*/
1160
1283
async convertIssuesAndComments (
1161
1284
str : string ,
1162
- item : GitLabIssue | GitLabMergeRequest | GitLabNote | MilestoneImport ,
1163
- add_line : boolean = true
1285
+ item : GitLabIssue | GitLabMergeRequest | GitLabNote | MilestoneImport | GitLabDiscussionNote ,
1286
+ add_line : boolean = true ,
1287
+ add_line_ref : boolean = true ,
1164
1288
) : Promise < string > {
1165
1289
// A note on implementation:
1166
1290
// We don't convert project names once at the beginning because otherwise
@@ -1176,7 +1300,7 @@ export class GithubHelper {
1176
1300
settings . projectmap !== null &&
1177
1301
Object . keys ( settings . projectmap ) . length > 0 ;
1178
1302
1179
- if ( add_line ) str = GithubHelper . addMigrationLine ( str , item , repoLink ) ;
1303
+ if ( add_line ) str = GithubHelper . addMigrationLine ( str , item , repoLink , add_line_ref ) ;
1180
1304
let reString = '' ;
1181
1305
1182
1306
// Store usernames found in the text
@@ -1348,7 +1472,7 @@ export class GithubHelper {
1348
1472
* Adds a line of text at the beginning of a comment that indicates who, when
1349
1473
* and from GitLab.
1350
1474
*/
1351
- static addMigrationLine ( str : string , item : any , repoLink : string ) : string {
1475
+ static addMigrationLine ( str : string , item : any , repoLink : string , add_line_ref : boolean = true ) : string {
1352
1476
if ( ! item || ! item . author || ! item . author . username || ! item . created_at ) {
1353
1477
return str ;
1354
1478
}
@@ -1368,11 +1492,12 @@ export class GithubHelper {
1368
1492
dateformatOptions
1369
1493
) ;
1370
1494
1371
- const attribution = `In GitLab by @${ item . author . username } on ${ formattedDate } ` ;
1495
+ const attribution = `*** In GitLab by @${ item . author . username } on ${ formattedDate } :*** ` ;
1372
1496
const lineRef =
1373
- item && item . position
1497
+ item && item . position && add_line_ref
1374
1498
? GithubHelper . createLineRef ( item . position , repoLink )
1375
1499
: '' ;
1500
+
1376
1501
const summary = attribution + ( lineRef ? `\n\n${ lineRef } ` : '' ) ;
1377
1502
1378
1503
return `${ summary } \n\n${ str } ` ;
@@ -1392,7 +1517,7 @@ export class GithubHelper {
1392
1517
return '' ;
1393
1518
}
1394
1519
const base_sha = position . base_sha ;
1395
- const head_sha = position . head_sha ;
1520
+ let head_sha = position . head_sha ;
1396
1521
var path = '' ;
1397
1522
var line = '' ;
1398
1523
var slug = '' ;
@@ -1416,7 +1541,22 @@ export class GithubHelper {
1416
1541
}
1417
1542
// Mention the file and line number. If we can't get this for some reason then use the commit id instead.
1418
1543
const ref = path && line ? `${ path } line ${ line } ` : `${ head_sha } ` ;
1419
- return `Commented on [${ ref } ](${ repoLink } /compare/${ base_sha } ..${ head_sha } ${ slug } )\n\n` ;
1544
+ let lineRef = `Commented on [${ ref } ](${ repoLink } /compare/${ base_sha } ..${ head_sha } ${ slug } )\n\n` ;
1545
+
1546
+ if ( position . line_range . start . type === 'new' ) {
1547
+ const startLine = position . line_range . start . new_line ;
1548
+ const endLine = position . line_range . end . new_line ;
1549
+ const lineRange = ( startLine !== endLine ) ? `L${ startLine } -L${ endLine } ` : `L${ startLine } ` ;
1550
+ lineRef += `${ repoLink } /blob/${ head_sha } /${ path } #${ lineRange } \n\n` ;
1551
+ }
1552
+ else {
1553
+ const startLine = position . line_range . start . old_line ;
1554
+ const endLine = position . line_range . end . old_line ;
1555
+ const lineRange = ( startLine !== endLine ) ? `L${ startLine } -L${ endLine } ` : `L${ startLine } ` ;
1556
+ lineRef += `${ repoLink } /blob/${ head_sha } /${ path } #${ lineRange } \n\n` ;
1557
+ }
1558
+
1559
+ return lineRef ;
1420
1560
}
1421
1561
1422
1562
/**
0 commit comments