@@ -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 ,
@@ -555,6 +557,85 @@ export class GithubHelper {
555
557
) ;
556
558
return comments ;
557
559
}
560
+
561
+ /**
562
+ *
563
+ * @param discussions
564
+ * @returns Comments ready for requestImportIssue()
565
+ */
566
+ async processDiscussionsIntoComments (
567
+ discussions : GitLabDiscussion [ ]
568
+ ) : Promise < CommentImport [ ] > {
569
+ if ( ! discussions || ! discussions . length ) {
570
+ console . log ( `\t...no comments available, nothing to migrate.` ) ;
571
+ return [ ] ;
572
+ }
573
+
574
+ let comments : CommentImport [ ] = [ ] ;
575
+
576
+ // sort notes in ascending order of when they were created (by id)
577
+ discussions = discussions . sort ( ( a , b ) => Number . parseInt ( a . id ) - Number . parseInt ( b . id ) ) ;
578
+
579
+ let nrOfMigratedNotes = 0 ;
580
+ let nrOfSkippedNotes = 0 ;
581
+ for ( let discussion of discussions ) {
582
+ let discussionComments = [ ] ;
583
+
584
+ for ( let note of discussion . notes ) {
585
+ if ( this . checkIfNoteCanBeSkipped ( note . body ) ) {
586
+ nrOfSkippedNotes ++ ;
587
+ continue ;
588
+ }
589
+
590
+ let username = note . author . username as string ;
591
+ this . users . add ( username ) ;
592
+ let userIsPoster =
593
+ ( settings . usermap &&
594
+ settings . usermap [ username ] ===
595
+ settings . github . token_owner ) ||
596
+ username === settings . github . token_owner ;
597
+
598
+ // only add line ref for first note of discussion
599
+ const add_line_ref = discussion . notes . indexOf ( note ) === 0 ;
600
+
601
+ discussionComments . push ( {
602
+ created_at : note . created_at ,
603
+ body : await this . convertIssuesAndComments (
604
+ note . body ,
605
+ note ,
606
+ ! userIsPoster || ! note . body ,
607
+ add_line_ref ,
608
+ ) ,
609
+ } ) ;
610
+
611
+ nrOfMigratedNotes ++ ;
612
+ }
613
+
614
+ // Combine notes for discussion into one comment
615
+ if ( discussionComments . length == 1 ) {
616
+ comments . push ( discussionComments [ 0 ] ) ;
617
+ }
618
+ else if ( discussionComments . length > 1 ) {
619
+ let combinedBody = '**Discussion in GitLab:**\n\n' ;
620
+ let first_created_at = discussionComments [ 0 ] . created_at ;
621
+
622
+ combinedBody += discussionComments . map ( comment => comment . body ) . join ( '\n\n' ) ;
623
+
624
+ comments . push ( {
625
+ created_at : first_created_at ,
626
+ body : combinedBody ,
627
+ } ) ;
628
+ }
629
+ }
630
+
631
+ console . log (
632
+ `\t...Done creating discussion comments (migrated ${ nrOfMigratedNotes } comments, skipped ${
633
+ nrOfSkippedNotes
634
+ } comments)`
635
+ ) ;
636
+ return comments ;
637
+ }
638
+
558
639
/**
559
640
* Calls the preview API for issue importing
560
641
*
@@ -685,7 +766,7 @@ export class GithubHelper {
685
766
* Return false when it got skipped, otherwise true.
686
767
*/
687
768
async processNote (
688
- note : GitLabNote ,
769
+ note : GitLabNote | GitLabDiscussionNote ,
689
770
githubIssue : Pick < GitHubIssue | GitHubPullRequest , 'number' >
690
771
) {
691
772
if ( this . checkIfNoteCanBeSkipped ( note . body ) ) return false ;
@@ -960,10 +1041,10 @@ export class GithubHelper {
960
1041
'\t...this is a placeholder for a deleted GitLab merge request, no comments are created.'
961
1042
) ;
962
1043
} else {
963
- let notes = await this . gitlabHelper . getAllMergeRequestNotes (
1044
+ let discussions = await this . gitlabHelper . getAllMergeRequestDiscussions (
964
1045
mergeRequest . iid
965
1046
) ;
966
- comments = await this . processNotesIntoComments ( notes ) ;
1047
+ comments = await this . processDiscussionsIntoComments ( discussions ) ;
967
1048
}
968
1049
969
1050
return this . requestImportIssue ( props , comments ) ;
@@ -1004,30 +1085,72 @@ export class GithubHelper {
1004
1085
return Promise . resolve ( ) ;
1005
1086
}
1006
1087
1007
- let notes = await this . gitlabHelper . getAllMergeRequestNotes (
1088
+ let discussions = await this . gitlabHelper . getAllMergeRequestDiscussions (
1008
1089
mergeRequest . iid
1009
1090
) ;
1010
1091
1011
1092
// if there are no notes, then there is nothing to do!
1012
- if ( notes . length === 0 ) {
1093
+ if ( discussions . length === 0 ) {
1013
1094
console . log (
1014
1095
`\t...no pull request comments available, nothing to migrate.`
1015
1096
) ;
1016
1097
return ;
1017
1098
}
1018
1099
1019
1100
// Sort notes in ascending order of when they were created (by id)
1020
- notes = notes . sort ( ( a , b ) => a . id - b . id ) ;
1101
+ discussions = discussions . sort ( ( a , b ) => a . notes [ 0 ] . id - b . notes [ 0 ] . id ) ;
1021
1102
1022
1103
let nrOfMigratedNotes = 0 ;
1023
- for ( let note of notes ) {
1024
- const gotMigrated = await this . processNote ( note , pullRequest ) ;
1025
- if ( gotMigrated ) nrOfMigratedNotes ++ ;
1104
+ let nrOfSkippedNotes = 0 ;
1105
+ for ( let discussion of discussions ) {
1106
+ if ( discussion . individual_note ) {
1107
+ const gotMigrated = await this . processNote ( discussion . notes [ 0 ] , pullRequest ) ;
1108
+ if ( gotMigrated ) {
1109
+ nrOfMigratedNotes ++ ;
1110
+ }
1111
+ else {
1112
+ nrOfSkippedNotes ++ ;
1113
+ }
1114
+ }
1115
+ else {
1116
+ // console.log('Processing discussion:');
1117
+ let discussionBody = '**Discussion in GitLab:**\n\n' ;
1118
+
1119
+ for ( let note of discussion . notes ) {
1120
+ if ( this . checkIfNoteCanBeSkipped ( note . body ) ) {
1121
+ nrOfSkippedNotes ++ ;
1122
+ continue ;
1123
+ }
1124
+
1125
+ const add_line_ref = discussion . notes . indexOf ( note ) === 0 ;
1126
+ let bodyConverted = await this . convertIssuesAndComments ( note . body , note , true , add_line_ref ) ;
1127
+ discussionBody += bodyConverted ;
1128
+ discussionBody += '\n\n' ;
1129
+ nrOfMigratedNotes ++ ;
1130
+ }
1131
+
1132
+ await utils . sleep ( this . delayInMs ) ;
1133
+
1134
+ if ( ! settings . dryRun ) {
1135
+ await this . githubApi . issues
1136
+ . createComment ( {
1137
+ owner : this . githubOwner ,
1138
+ repo : this . githubRepo ,
1139
+ issue_number : pullRequest . number ,
1140
+ body : discussionBody ,
1141
+ } )
1142
+ . catch ( x => {
1143
+ console . error ( 'could not create GitHub issue comment!' ) ;
1144
+ console . error ( x ) ;
1145
+ process . exit ( 1 ) ;
1146
+ } ) ;
1147
+ }
1148
+ }
1026
1149
}
1027
1150
1028
1151
console . log (
1029
1152
`\t...Done creating pull request comments (migrated ${ nrOfMigratedNotes } pull request comments, skipped ${
1030
- notes . length - nrOfMigratedNotes
1153
+ nrOfSkippedNotes
1031
1154
} pull request comments)`
1032
1155
) ;
1033
1156
}
@@ -1153,8 +1276,9 @@ export class GithubHelper {
1153
1276
*/
1154
1277
async convertIssuesAndComments (
1155
1278
str : string ,
1156
- item : GitLabIssue | GitLabMergeRequest | GitLabNote | MilestoneImport ,
1157
- add_line : boolean = true
1279
+ item : GitLabIssue | GitLabMergeRequest | GitLabNote | MilestoneImport | GitLabDiscussionNote ,
1280
+ add_line : boolean = true ,
1281
+ add_line_ref : boolean = true ,
1158
1282
) : Promise < string > {
1159
1283
// A note on implementation:
1160
1284
// We don't convert project names once at the beginning because otherwise
@@ -1170,7 +1294,7 @@ export class GithubHelper {
1170
1294
settings . projectmap !== null &&
1171
1295
Object . keys ( settings . projectmap ) . length > 0 ;
1172
1296
1173
- if ( add_line ) str = GithubHelper . addMigrationLine ( str , item , repoLink ) ;
1297
+ if ( add_line ) str = GithubHelper . addMigrationLine ( str , item , repoLink , add_line_ref ) ;
1174
1298
let reString = '' ;
1175
1299
1176
1300
// Store usernames found in the text
@@ -1342,7 +1466,7 @@ export class GithubHelper {
1342
1466
* Adds a line of text at the beginning of a comment that indicates who, when
1343
1467
* and from GitLab.
1344
1468
*/
1345
- static addMigrationLine ( str : string , item : any , repoLink : string ) : string {
1469
+ static addMigrationLine ( str : string , item : any , repoLink : string , add_line_ref : boolean = true ) : string {
1346
1470
if ( ! item || ! item . author || ! item . author . username || ! item . created_at ) {
1347
1471
return str ;
1348
1472
}
@@ -1362,11 +1486,12 @@ export class GithubHelper {
1362
1486
dateformatOptions
1363
1487
) ;
1364
1488
1365
- const attribution = `In GitLab by @${ item . author . username } on ${ formattedDate } ` ;
1489
+ const attribution = `*** In GitLab by @${ item . author . username } on ${ formattedDate } :*** ` ;
1366
1490
const lineRef =
1367
- item && item . position
1491
+ item && item . position && add_line_ref
1368
1492
? GithubHelper . createLineRef ( item . position , repoLink )
1369
1493
: '' ;
1494
+
1370
1495
const summary = attribution + ( lineRef ? `\n\n${ lineRef } ` : '' ) ;
1371
1496
1372
1497
return `${ summary } \n\n${ str } ` ;
@@ -1386,7 +1511,7 @@ export class GithubHelper {
1386
1511
return '' ;
1387
1512
}
1388
1513
const base_sha = position . base_sha ;
1389
- const head_sha = position . head_sha ;
1514
+ let head_sha = position . head_sha ;
1390
1515
var path = '' ;
1391
1516
var line = '' ;
1392
1517
var slug = '' ;
@@ -1410,7 +1535,22 @@ export class GithubHelper {
1410
1535
}
1411
1536
// Mention the file and line number. If we can't get this for some reason then use the commit id instead.
1412
1537
const ref = path && line ? `${ path } line ${ line } ` : `${ head_sha } ` ;
1413
- return `Commented on [${ ref } ](${ repoLink } /compare/${ base_sha } ..${ head_sha } ${ slug } )\n\n` ;
1538
+ let lineRef = `Commented on [${ ref } ](${ repoLink } /compare/${ base_sha } ..${ head_sha } ${ slug } )\n\n` ;
1539
+
1540
+ if ( position . line_range . start . type === 'new' ) {
1541
+ const startLine = position . line_range . start . new_line ;
1542
+ const endLine = position . line_range . end . new_line ;
1543
+ const lineRange = ( startLine !== endLine ) ? `L${ startLine } -L${ endLine } ` : `L${ startLine } ` ;
1544
+ lineRef += `${ repoLink } /blob/${ head_sha } /${ path } #${ lineRange } \n\n` ;
1545
+ }
1546
+ else {
1547
+ const startLine = position . line_range . start . old_line ;
1548
+ const endLine = position . line_range . end . old_line ;
1549
+ const lineRange = ( startLine !== endLine ) ? `L${ startLine } -L${ endLine } ` : `L${ startLine } ` ;
1550
+ lineRef += `${ repoLink } /blob/${ head_sha } /${ path } #${ lineRange } \n\n` ;
1551
+ }
1552
+
1553
+ return lineRef ;
1414
1554
}
1415
1555
1416
1556
/**
0 commit comments