2020-04-28 16:46:47 +02:00
/*istanbul ignore start*/
"use strict" ;
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
exports . calcLineCount = calcLineCount ;
exports . merge = merge ;
/*istanbul ignore end*/
var
/*istanbul ignore start*/
_create = require ( "./create" )
/*istanbul ignore end*/
;
var
/*istanbul ignore start*/
_parse = require ( "./parse" )
/*istanbul ignore end*/
;
var
/*istanbul ignore start*/
_array = require ( "../util/array" )
/*istanbul ignore end*/
;
2021-07-27 22:26:09 +00:00
/*istanbul ignore start*/ function _toConsumableArray ( arr ) { return _arrayWithoutHoles ( arr ) || _iterableToArray ( arr ) || _unsupportedIterableToArray ( arr ) || _nonIterableSpread ( ) ; }
function _nonIterableSpread ( ) { throw new TypeError ( "Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method." ) ; }
function _unsupportedIterableToArray ( o , minLen ) { if ( ! o ) return ; if ( typeof o === "string" ) return _arrayLikeToArray ( o , minLen ) ; var n = Object . prototype . toString . call ( o ) . slice ( 8 , - 1 ) ; if ( n === "Object" && o . constructor ) n = o . constructor . name ; if ( n === "Map" || n === "Set" ) return Array . from ( o ) ; if ( n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/ . test ( n ) ) return _arrayLikeToArray ( o , minLen ) ; }
2024-09-16 17:29:58 +00:00
function _iterableToArray ( iter ) { if ( typeof Symbol !== "undefined" && iter [ Symbol . iterator ] != null || iter [ "@@iterator" ] != null ) return Array . from ( iter ) ; }
2021-07-27 22:26:09 +00:00
function _arrayWithoutHoles ( arr ) { if ( Array . isArray ( arr ) ) return _arrayLikeToArray ( arr ) ; }
2024-09-16 17:29:58 +00:00
function _arrayLikeToArray ( arr , len ) { if ( len == null || len > arr . length ) len = arr . length ; for ( var i = 0 , arr2 = new Array ( len ) ; i < len ; i ++ ) arr2 [ i ] = arr [ i ] ; return arr2 ; }
2020-04-28 16:46:47 +02:00
/*istanbul ignore end*/
function calcLineCount ( hunk ) {
2024-09-16 17:29:58 +00:00
var
/*istanbul ignore start*/
_calcOldNewLineCount =
/*istanbul ignore end*/
calcOldNewLineCount ( hunk . lines ) ,
/*istanbul ignore start*/
/*istanbul ignore end*/
oldLines = _calcOldNewLineCount . oldLines ,
/*istanbul ignore start*/
/*istanbul ignore end*/
newLines = _calcOldNewLineCount . newLines ;
2020-04-28 16:46:47 +02:00
if ( oldLines !== undefined ) {
hunk . oldLines = oldLines ;
} else {
delete hunk . oldLines ;
}
if ( newLines !== undefined ) {
hunk . newLines = newLines ;
} else {
delete hunk . newLines ;
}
}
function merge ( mine , theirs , base ) {
mine = loadPatch ( mine , base ) ;
theirs = loadPatch ( theirs , base ) ;
2024-09-16 17:29:58 +00:00
var ret = { } ;
// For index we just let it pass through as it doesn't have any necessary meaning.
2020-04-28 16:46:47 +02:00
// Leaving sanity checks on this to the API consumer that may know more about the
// meaning in their own context.
if ( mine . index || theirs . index ) {
ret . index = mine . index || theirs . index ;
}
if ( mine . newFileName || theirs . newFileName ) {
if ( ! fileNameChanged ( mine ) ) {
// No header or no change in ours, use theirs (and ours if theirs does not exist)
ret . oldFileName = theirs . oldFileName || mine . oldFileName ;
ret . newFileName = theirs . newFileName || mine . newFileName ;
ret . oldHeader = theirs . oldHeader || mine . oldHeader ;
ret . newHeader = theirs . newHeader || mine . newHeader ;
} else if ( ! fileNameChanged ( theirs ) ) {
// No header or no change in theirs, use ours
ret . oldFileName = mine . oldFileName ;
ret . newFileName = mine . newFileName ;
ret . oldHeader = mine . oldHeader ;
ret . newHeader = mine . newHeader ;
} else {
// Both changed... figure it out
ret . oldFileName = selectField ( ret , mine . oldFileName , theirs . oldFileName ) ;
ret . newFileName = selectField ( ret , mine . newFileName , theirs . newFileName ) ;
ret . oldHeader = selectField ( ret , mine . oldHeader , theirs . oldHeader ) ;
ret . newHeader = selectField ( ret , mine . newHeader , theirs . newHeader ) ;
}
}
ret . hunks = [ ] ;
var mineIndex = 0 ,
2024-09-16 17:29:58 +00:00
theirsIndex = 0 ,
mineOffset = 0 ,
theirsOffset = 0 ;
2020-04-28 16:46:47 +02:00
while ( mineIndex < mine . hunks . length || theirsIndex < theirs . hunks . length ) {
var mineCurrent = mine . hunks [ mineIndex ] || {
2024-09-16 17:29:58 +00:00
oldStart : Infinity
} ,
theirsCurrent = theirs . hunks [ theirsIndex ] || {
oldStart : Infinity
} ;
2020-04-28 16:46:47 +02:00
if ( hunkBefore ( mineCurrent , theirsCurrent ) ) {
// This patch does not overlap with any of the others, yay.
ret . hunks . push ( cloneHunk ( mineCurrent , mineOffset ) ) ;
mineIndex ++ ;
theirsOffset += mineCurrent . newLines - mineCurrent . oldLines ;
} else if ( hunkBefore ( theirsCurrent , mineCurrent ) ) {
// This patch does not overlap with any of the others, yay.
ret . hunks . push ( cloneHunk ( theirsCurrent , theirsOffset ) ) ;
theirsIndex ++ ;
mineOffset += theirsCurrent . newLines - theirsCurrent . oldLines ;
} else {
// Overlap, merge as best we can
var mergedHunk = {
oldStart : Math . min ( mineCurrent . oldStart , theirsCurrent . oldStart ) ,
oldLines : 0 ,
newStart : Math . min ( mineCurrent . newStart + mineOffset , theirsCurrent . oldStart + theirsOffset ) ,
newLines : 0 ,
lines : [ ]
} ;
mergeLines ( mergedHunk , mineCurrent . oldStart , mineCurrent . lines , theirsCurrent . oldStart , theirsCurrent . lines ) ;
theirsIndex ++ ;
mineIndex ++ ;
ret . hunks . push ( mergedHunk ) ;
}
}
return ret ;
}
function loadPatch ( param , base ) {
if ( typeof param === 'string' ) {
if ( /^@@/m . test ( param ) || /^Index:/m . test ( param ) ) {
return (
/*istanbul ignore start*/
( 0 ,
/*istanbul ignore end*/
/*istanbul ignore start*/
_parse
/*istanbul ignore end*/
.
/*istanbul ignore start*/
parsePatch )
/*istanbul ignore end*/
( param ) [ 0 ]
) ;
}
if ( ! base ) {
throw new Error ( 'Must provide a base reference or pass in a patch' ) ;
}
return (
/*istanbul ignore start*/
( 0 ,
/*istanbul ignore end*/
/*istanbul ignore start*/
_create
/*istanbul ignore end*/
.
/*istanbul ignore start*/
structuredPatch )
/*istanbul ignore end*/
( undefined , undefined , base , param )
) ;
}
return param ;
}
function fileNameChanged ( patch ) {
return patch . newFileName && patch . newFileName !== patch . oldFileName ;
}
function selectField ( index , mine , theirs ) {
if ( mine === theirs ) {
return mine ;
} else {
index . conflict = true ;
return {
mine : mine ,
theirs : theirs
} ;
}
}
function hunkBefore ( test , check ) {
return test . oldStart < check . oldStart && test . oldStart + test . oldLines < check . oldStart ;
}
function cloneHunk ( hunk , offset ) {
return {
oldStart : hunk . oldStart ,
oldLines : hunk . oldLines ,
newStart : hunk . newStart + offset ,
newLines : hunk . newLines ,
lines : hunk . lines
} ;
}
function mergeLines ( hunk , mineOffset , mineLines , theirOffset , theirLines ) {
// This will generally result in a conflicted hunk, but there are cases where the context
// is the only overlap where we can successfully merge the content here.
var mine = {
2024-09-16 17:29:58 +00:00
offset : mineOffset ,
lines : mineLines ,
index : 0
} ,
their = {
offset : theirOffset ,
lines : theirLines ,
index : 0
} ;
2020-04-28 16:46:47 +02:00
2024-09-16 17:29:58 +00:00
// Handle any leading content
2020-04-28 16:46:47 +02:00
insertLeading ( hunk , mine , their ) ;
2024-09-16 17:29:58 +00:00
insertLeading ( hunk , their , mine ) ;
2020-04-28 16:46:47 +02:00
2024-09-16 17:29:58 +00:00
// Now in the overlap content. Scan through and select the best changes from each.
2020-04-28 16:46:47 +02:00
while ( mine . index < mine . lines . length && their . index < their . lines . length ) {
var mineCurrent = mine . lines [ mine . index ] ,
2024-09-16 17:29:58 +00:00
theirCurrent = their . lines [ their . index ] ;
2020-04-28 16:46:47 +02:00
if ( ( mineCurrent [ 0 ] === '-' || mineCurrent [ 0 ] === '+' ) && ( theirCurrent [ 0 ] === '-' || theirCurrent [ 0 ] === '+' ) ) {
// Both modified ...
mutualChange ( hunk , mine , their ) ;
} else if ( mineCurrent [ 0 ] === '+' && theirCurrent [ 0 ] === ' ' ) {
/*istanbul ignore start*/
var _hunk$lines ;
/*istanbul ignore end*/
// Mine inserted
/*istanbul ignore start*/
/*istanbul ignore end*/
/*istanbul ignore start*/
2021-07-27 22:26:09 +00:00
( _hunk$lines =
2020-04-28 16:46:47 +02:00
/*istanbul ignore end*/
2021-07-27 22:26:09 +00:00
hunk . lines ) . push . apply (
2020-04-28 16:46:47 +02:00
/*istanbul ignore start*/
_hunk$lines
/*istanbul ignore end*/
,
/*istanbul ignore start*/
_toConsumableArray (
/*istanbul ignore end*/
collectChange ( mine ) ) ) ;
} else if ( theirCurrent [ 0 ] === '+' && mineCurrent [ 0 ] === ' ' ) {
/*istanbul ignore start*/
var _hunk$lines2 ;
/*istanbul ignore end*/
// Theirs inserted
/*istanbul ignore start*/
/*istanbul ignore end*/
/*istanbul ignore start*/
2021-07-27 22:26:09 +00:00
( _hunk$lines2 =
2020-04-28 16:46:47 +02:00
/*istanbul ignore end*/
2021-07-27 22:26:09 +00:00
hunk . lines ) . push . apply (
2020-04-28 16:46:47 +02:00
/*istanbul ignore start*/
_hunk$lines2
/*istanbul ignore end*/
,
/*istanbul ignore start*/
_toConsumableArray (
/*istanbul ignore end*/
collectChange ( their ) ) ) ;
} else if ( mineCurrent [ 0 ] === '-' && theirCurrent [ 0 ] === ' ' ) {
// Mine removed or edited
removal ( hunk , mine , their ) ;
} else if ( theirCurrent [ 0 ] === '-' && mineCurrent [ 0 ] === ' ' ) {
// Their removed or edited
removal ( hunk , their , mine , true ) ;
} else if ( mineCurrent === theirCurrent ) {
// Context identity
hunk . lines . push ( mineCurrent ) ;
mine . index ++ ;
their . index ++ ;
} else {
// Context mismatch
conflict ( hunk , collectChange ( mine ) , collectChange ( their ) ) ;
}
2024-09-16 17:29:58 +00:00
}
2020-04-28 16:46:47 +02:00
2024-09-16 17:29:58 +00:00
// Now push anything that may be remaining
2020-04-28 16:46:47 +02:00
insertTrailing ( hunk , mine ) ;
insertTrailing ( hunk , their ) ;
calcLineCount ( hunk ) ;
}
function mutualChange ( hunk , mine , their ) {
var myChanges = collectChange ( mine ) ,
2024-09-16 17:29:58 +00:00
theirChanges = collectChange ( their ) ;
2020-04-28 16:46:47 +02:00
if ( allRemoves ( myChanges ) && allRemoves ( theirChanges ) ) {
// Special case for remove changes that are supersets of one another
if (
/*istanbul ignore start*/
( 0 ,
/*istanbul ignore end*/
/*istanbul ignore start*/
_array
/*istanbul ignore end*/
.
/*istanbul ignore start*/
arrayStartsWith )
/*istanbul ignore end*/
( myChanges , theirChanges ) && skipRemoveSuperset ( their , myChanges , myChanges . length - theirChanges . length ) ) {
/*istanbul ignore start*/
var _hunk$lines3 ;
/*istanbul ignore end*/
/*istanbul ignore start*/
/*istanbul ignore end*/
/*istanbul ignore start*/
2021-07-27 22:26:09 +00:00
( _hunk$lines3 =
2020-04-28 16:46:47 +02:00
/*istanbul ignore end*/
2021-07-27 22:26:09 +00:00
hunk . lines ) . push . apply (
2020-04-28 16:46:47 +02:00
/*istanbul ignore start*/
_hunk$lines3
/*istanbul ignore end*/
,
/*istanbul ignore start*/
_toConsumableArray (
/*istanbul ignore end*/
myChanges ) ) ;
return ;
} else if (
/*istanbul ignore start*/
( 0 ,
/*istanbul ignore end*/
/*istanbul ignore start*/
_array
/*istanbul ignore end*/
.
/*istanbul ignore start*/
arrayStartsWith )
/*istanbul ignore end*/
( theirChanges , myChanges ) && skipRemoveSuperset ( mine , theirChanges , theirChanges . length - myChanges . length ) ) {
/*istanbul ignore start*/
var _hunk$lines4 ;
/*istanbul ignore end*/
/*istanbul ignore start*/
/*istanbul ignore end*/
/*istanbul ignore start*/
2021-07-27 22:26:09 +00:00
( _hunk$lines4 =
2020-04-28 16:46:47 +02:00
/*istanbul ignore end*/
2021-07-27 22:26:09 +00:00
hunk . lines ) . push . apply (
2020-04-28 16:46:47 +02:00
/*istanbul ignore start*/
_hunk$lines4
/*istanbul ignore end*/
,
/*istanbul ignore start*/
_toConsumableArray (
/*istanbul ignore end*/
theirChanges ) ) ;
return ;
}
} else if (
/*istanbul ignore start*/
( 0 ,
/*istanbul ignore end*/
/*istanbul ignore start*/
_array
/*istanbul ignore end*/
.
/*istanbul ignore start*/
arrayEqual )
/*istanbul ignore end*/
( myChanges , theirChanges ) ) {
/*istanbul ignore start*/
var _hunk$lines5 ;
/*istanbul ignore end*/
/*istanbul ignore start*/
/*istanbul ignore end*/
/*istanbul ignore start*/
2021-07-27 22:26:09 +00:00
( _hunk$lines5 =
2020-04-28 16:46:47 +02:00
/*istanbul ignore end*/
2021-07-27 22:26:09 +00:00
hunk . lines ) . push . apply (
2020-04-28 16:46:47 +02:00
/*istanbul ignore start*/
_hunk$lines5
/*istanbul ignore end*/
,
/*istanbul ignore start*/
_toConsumableArray (
/*istanbul ignore end*/
myChanges ) ) ;
return ;
}
conflict ( hunk , myChanges , theirChanges ) ;
}
function removal ( hunk , mine , their , swap ) {
var myChanges = collectChange ( mine ) ,
2024-09-16 17:29:58 +00:00
theirChanges = collectContext ( their , myChanges ) ;
2020-04-28 16:46:47 +02:00
if ( theirChanges . merged ) {
/*istanbul ignore start*/
var _hunk$lines6 ;
/*istanbul ignore end*/
/*istanbul ignore start*/
/*istanbul ignore end*/
/*istanbul ignore start*/
2021-07-27 22:26:09 +00:00
( _hunk$lines6 =
2020-04-28 16:46:47 +02:00
/*istanbul ignore end*/
2021-07-27 22:26:09 +00:00
hunk . lines ) . push . apply (
2020-04-28 16:46:47 +02:00
/*istanbul ignore start*/
_hunk$lines6
/*istanbul ignore end*/
,
/*istanbul ignore start*/
_toConsumableArray (
/*istanbul ignore end*/
theirChanges . merged ) ) ;
} else {
conflict ( hunk , swap ? theirChanges : myChanges , swap ? myChanges : theirChanges ) ;
}
}
function conflict ( hunk , mine , their ) {
hunk . conflict = true ;
hunk . lines . push ( {
conflict : true ,
mine : mine ,
theirs : their
} ) ;
}
function insertLeading ( hunk , insert , their ) {
while ( insert . offset < their . offset && insert . index < insert . lines . length ) {
var line = insert . lines [ insert . index ++ ] ;
hunk . lines . push ( line ) ;
insert . offset ++ ;
}
}
function insertTrailing ( hunk , insert ) {
while ( insert . index < insert . lines . length ) {
var line = insert . lines [ insert . index ++ ] ;
hunk . lines . push ( line ) ;
}
}
function collectChange ( state ) {
var ret = [ ] ,
2024-09-16 17:29:58 +00:00
operation = state . lines [ state . index ] [ 0 ] ;
2020-04-28 16:46:47 +02:00
while ( state . index < state . lines . length ) {
2024-09-16 17:29:58 +00:00
var line = state . lines [ state . index ] ;
2020-04-28 16:46:47 +02:00
2024-09-16 17:29:58 +00:00
// Group additions that are immediately after subtractions and treat them as one "atomic" modify change.
2020-04-28 16:46:47 +02:00
if ( operation === '-' && line [ 0 ] === '+' ) {
operation = '+' ;
}
if ( operation === line [ 0 ] ) {
ret . push ( line ) ;
state . index ++ ;
} else {
break ;
}
}
return ret ;
}
function collectContext ( state , matchChanges ) {
var changes = [ ] ,
2024-09-16 17:29:58 +00:00
merged = [ ] ,
matchIndex = 0 ,
contextChanges = false ,
conflicted = false ;
2020-04-28 16:46:47 +02:00
while ( matchIndex < matchChanges . length && state . index < state . lines . length ) {
var change = state . lines [ state . index ] ,
2024-09-16 17:29:58 +00:00
match = matchChanges [ matchIndex ] ;
2020-04-28 16:46:47 +02:00
2024-09-16 17:29:58 +00:00
// Once we've hit our add, then we are done
2020-04-28 16:46:47 +02:00
if ( match [ 0 ] === '+' ) {
break ;
}
contextChanges = contextChanges || change [ 0 ] !== ' ' ;
merged . push ( match ) ;
2024-09-16 17:29:58 +00:00
matchIndex ++ ;
2020-04-28 16:46:47 +02:00
2024-09-16 17:29:58 +00:00
// Consume any additions in the other block as a conflict to attempt
// to pull in the remaining context after this
2020-04-28 16:46:47 +02:00
if ( change [ 0 ] === '+' ) {
conflicted = true ;
while ( change [ 0 ] === '+' ) {
changes . push ( change ) ;
change = state . lines [ ++ state . index ] ;
}
}
if ( match . substr ( 1 ) === change . substr ( 1 ) ) {
changes . push ( change ) ;
state . index ++ ;
} else {
conflicted = true ;
}
}
if ( ( matchChanges [ matchIndex ] || '' ) [ 0 ] === '+' && contextChanges ) {
conflicted = true ;
}
if ( conflicted ) {
return changes ;
}
while ( matchIndex < matchChanges . length ) {
merged . push ( matchChanges [ matchIndex ++ ] ) ;
}
return {
merged : merged ,
changes : changes
} ;
}
function allRemoves ( changes ) {
return changes . reduce ( function ( prev , change ) {
return prev && change [ 0 ] === '-' ;
} , true ) ;
}
function skipRemoveSuperset ( state , removeChanges , delta ) {
for ( var i = 0 ; i < delta ; i ++ ) {
var changeContent = removeChanges [ removeChanges . length - delta + i ] . substr ( 1 ) ;
if ( state . lines [ state . index + i ] !== ' ' + changeContent ) {
return false ;
}
}
state . index += delta ;
return true ;
}
function calcOldNewLineCount ( lines ) {
var oldLines = 0 ;
var newLines = 0 ;
lines . forEach ( function ( line ) {
if ( typeof line !== 'string' ) {
var myCount = calcOldNewLineCount ( line . mine ) ;
var theirCount = calcOldNewLineCount ( line . theirs ) ;
if ( oldLines !== undefined ) {
if ( myCount . oldLines === theirCount . oldLines ) {
oldLines += myCount . oldLines ;
} else {
oldLines = undefined ;
}
}
if ( newLines !== undefined ) {
if ( myCount . newLines === theirCount . newLines ) {
newLines += myCount . newLines ;
} else {
newLines = undefined ;
}
}
} else {
if ( newLines !== undefined && ( line [ 0 ] === '+' || line [ 0 ] === ' ' ) ) {
newLines ++ ;
}
if ( oldLines !== undefined && ( line [ 0 ] === '-' || line [ 0 ] === ' ' ) ) {
oldLines ++ ;
}
}
} ) ;
return {
oldLines : oldLines ,
newLines : newLines
} ;
}
2024-09-16 17:29:58 +00:00
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfY3JlYXRlIiwicmVxdWlyZSIsIl9wYXJzZSIsIl9hcnJheSIsIl90b0NvbnN1bWFibGVBcnJheSIsImFyciIsIl9hcnJheVdpdGhvdXRIb2xlcyIsIl9pdGVyYWJsZVRvQXJyYXkiLCJfdW5zdXBwb3J0ZWRJdGVyYWJsZVRvQXJyYXkiLCJfbm9uSXRlcmFibGVTcHJlYWQiLCJUeXBlRXJyb3IiLCJvIiwibWluTGVuIiwiX2FycmF5TGlrZVRvQXJyYXkiLCJuIiwiT2JqZWN0IiwicHJvdG90eXBlIiwidG9TdHJpbmciLCJjYWxsIiwic2xpY2UiLCJjb25zdHJ1Y3RvciIsIm5hbWUiLCJBcnJheSIsImZyb20iLCJ0ZXN0IiwiaXRlciIsIlN5bWJvbCIsIml0ZXJhdG9yIiwiaXNBcnJheSIsImxlbiIsImxlbmd0aCIsImkiLCJhcnIyIiwiY2FsY0xpbmVDb3VudCIsImh1bmsiLCJfY2FsY09sZE5ld0xpbmVDb3VudCIsImNhbGNPbGROZXdMaW5lQ291bnQiLCJsaW5lcyIsIm9sZExpbmVzIiwibmV3TGluZXMiLCJ1bmRlZmluZWQiLCJtZXJnZSIsIm1pbmUiLCJ0aGVpcnMiLCJiYXNlIiwibG9hZFBhdGNoIiwicmV0IiwiaW5kZXgiLCJuZXdGaWxlTmFtZSIsImZpbGVOYW1lQ2hhbmdlZCIsIm9sZEZpbGVOYW1lIiwib2xkSGVhZGVyIiwibmV3SGVhZGVyIiwic2VsZWN0RmllbGQiLCJodW5rcyIsIm1pbmVJbmRleCIsInRoZWlyc0luZGV4IiwibWluZU9mZnNldCIsInRoZWlyc09mZnNldCIsIm1pbmVDdXJyZW50Iiwib2xkU3RhcnQiLCJJbmZpbml0eSIsInRoZWlyc0N1cnJlbnQiLCJodW5rQmVmb3JlIiwicHVzaCIsImNsb25lSHVuayIsIm1lcmdlZEh1bmsiLCJNYXRoIiwibWluIiwibmV3U3RhcnQiLCJtZXJnZUxpbmVzIiwicGFyYW0iLCJwYXJzZVBhdGNoIiwiRXJyb3IiLCJzdHJ1Y3R1cmVkUGF0Y2giLCJwYXRjaCIsImNvbmZsaWN0IiwiY2hlY2siLCJvZmZzZXQiLCJtaW5lTGluZXMiLCJ0aGVpck9mZnNldCIsInRoZWlyTGluZXMiLCJ0aGVpciIsImluc2VydExlYWRpbmciLCJ0aGVpckN1cnJlbnQiLCJtdXR1YWxDaGFuZ2UiLCJfaHVuayRsaW5lcyIsImFwcGx5IiwiY29sbGVjdENoYW5nZSIsIl9odW5rJGxpbmVzMiIsInJlbW92YWwiLCJpbnNlcnRUcmFpbGluZyIsIm15Q2hhbmdlcyIsInRoZWlyQ2hhbmdlcyIsImFsbFJlbW92ZXMiLCJhcnJheVN0YXJ0c1dpdGgiLCJza2lwUmVtb3ZlU3VwZXJzZXQiLCJfaHVuayRsaW5lczMiLCJfaHVuayRsaW5lczQiLCJhcnJheUVxdWFsIiwiX2h1bmskbGluZXM1Iiwic3dhcCIsImNvbGxlY3RDb250ZXh0IiwibWVyZ2VkIiwiX2h1bmskbGluZXM2IiwiaW5zZXJ0IiwibGluZSIsInN0YXRlIiwib3BlcmF0aW9uIiwibWF0Y2hDaGFuZ2VzIiwiY2hhbmdlcyIsIm1hdGNoSW5kZXgiLCJjb250ZXh0Q2hhbmdlcyIsImNvbmZsaWN0ZWQiLCJjaGFuZ2UiLCJtYXRjaCIsInN1YnN0ciIsInJlZHVjZSIsInByZXYiLCJyZW1vdmVDaGFuZ2VzIiwiZGVsdGEiLCJjaGFuZ2VDb250ZW50IiwiZm9yRWFjaCIsIm15Q291bnQiLCJ0aGVpckNvdW50Il0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BhdGNoL21lcmdlLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7c3RydWN0dXJlZFBhdGNofSBmcm9tICcuL2NyZWF0ZSc7XG5pbXBvcnQge3BhcnNlUGF0Y2h9IGZyb20gJy4vcGFyc2UnO1xuXG5pbXBvcnQge2FycmF5RXF1YWwsIGFycmF5U3RhcnRzV2l0aH0gZnJvbSAnLi4vdXRpbC9hcnJheSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBjYWxjTGluZUNvdW50KGh1bmspIHtcbiAgY29uc3Qge29sZExpbmVzLCBuZXdMaW5lc30gPSBjYWxjT2xkTmV3TGluZUNvdW50KGh1bmsubGluZXMpO1xuXG4gIGlmIChvbGRMaW5lcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgaHVuay5vbGRMaW5lcyA9IG9sZExpbmVzO1xuICB9IGVsc2Uge1xuICAgIGRlbGV0ZSBodW5rLm9sZExpbmVzO1xuICB9XG5cbiAgaWYgKG5ld0xpbmVzICE9PSB1bmRlZmluZWQpIHtcbiAgICBodW5rLm5ld0xpbmVzID0gbmV3TGluZXM7XG4gIH0gZWxzZSB7XG4gICAgZGVsZXRlIGh1bmsubmV3TGluZXM7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1lcmdlKG1pbmUsIHRoZWlycywgYmFzZSkge1xuICBtaW5lID0gbG9hZFBhdGNoKG1pbmUsIGJhc2UpO1xuICB0aGVpcnMgPSBsb2FkUGF0Y2godGhlaXJzLCBiYXNlKTtcblxuICBsZXQgcmV0ID0ge307XG5cbiAgLy8gRm9yIGluZGV4IHdlIGp1c3QgbGV0IGl0IHBhc3MgdGhyb3VnaCBhcyBpdCBkb2Vzbid0IGhhdmUgYW55IG5lY2Vzc2FyeSBtZWFuaW5nLlxuICAvLyBMZWF2aW5nIHNhbml0eSBjaGVja3Mgb24gdGhpcyB0byB0aGUgQVBJIGNvbnN1bWVyIHRoYXQgbWF5IGtub3cgbW9yZSBhYm91dCB0aGVcbiAgLy8gbWVhbmluZyBpbiB0aGVpciBvd24gY29udGV4dC5cbiAgaWYgKG1pbmUuaW5kZXggfHwgdGhlaXJzLmluZGV4KSB7XG4gICAgcmV0LmluZGV4ID0gbWluZS5pbmRleCB8fCB0aGVpcnMuaW5kZXg7XG4gIH1cblxuICBpZiAobWluZS5uZXdGaWxlTmFtZSB8fCB0aGVpcnMubmV3RmlsZU5hbWUpIHtcbiAgICBpZiAoIWZpbGVOYW1lQ2hhbmdlZChtaW5lKSkge1xuICAgICAgLy8gTm8gaGVhZGVyIG9yIG5vIGNoYW5nZSBpbiBvdXJzLCB1c2UgdGhlaXJzIChhbmQgb3VycyBpZiB0aGVpcnMgZG9lcyBub3QgZXhpc3QpXG4gICAgICByZXQub2xkRmlsZU5hbWUgPSB0aGVpcnMub2xkRmlsZU5hbWUgfHwgbWluZS5vbGRGaWxlTmFtZTtcbiAgICAgIHJldC5uZXdGaWxlTmFtZSA9IHRoZWlycy5uZXdGaWxlTmFtZSB8fCBtaW5lLm5ld0ZpbGVOYW1lO1xuICAgICAgcmV0Lm9sZEhlYWRlciA9IHRoZWlycy5vbGRIZWFkZXIgfHwgbWluZS5vbGRIZWFkZXI7XG4gICAgICByZXQubmV3SGVhZGVyID0gdGhlaXJzLm5ld0hlYWRlciB8fCBtaW5lLm5ld0hlYWRlcjtcbiAgICB9IGVsc2UgaWYgKCFmaWxlTmFtZUNoYW5nZWQodGhlaXJzKSkge1xuICAgICAgLy8gTm8gaGVhZGVyIG9yIG5vIGNoYW5nZSBpbiB0aGVpcnMsIHVzZSBvdXJzXG4gICAgICByZXQub2xkRmlsZU5hbWUgPSBtaW5lLm9sZEZpbGVOYW1lO1xuICAgICAgcmV0Lm5