import { eq , major , minor , patch , prerelease } from '@renovatebot/ruby-semver' ; import { SegmentElement , create , } from '@renovatebot/ruby-semver/dist/ruby/version.js' ; import { regEx } from '../../util/regex' ; interface RubyVersion { major : number ; minor : number ; patch : number ; prerelease : string [ ] | null ; } function releaseSegments ( version ) { const v = create ( version ) ; if ( v ) { return v . release ( ) . getSegments ( ) ; } return [ ] ; } const parse = ( version ) : RubyVersion => ( { major : major ( version ) , minor : minor ( version ) , patch : patch ( version ) , prerelease : prerelease ( version ) , } ) ; const adapt = ( left , right ) : string => left . split ( '.' ) . slice ( 0 , right . split ( '.' ) . length ) . join ( '.' ) ; const floor = ( version ) : string => [ ... releaseSegments ( version ) . slice ( 0 , - 1 ) , 0 ] . join ( '.' ) ; const incrementLastSegment = ( version ) : string => { const segments = releaseSegments ( version ) ; const nextLast = parseInt ( segments . pop ( ) as string , 10 ) + 1 ; return [ ... segments , nextLast ] . join ( '.' ) ; } ; const incrementMajor = ( maj , min , ptch , pre ) : number => ( min === 0 || ptch === 0 || pre . length === 0 ? maj + 1 : maj ) ; const incrementMinor = ( min , ptch , pre ) : number => ptch === 0 || pre . length === 0 ? min + 1 : min ; const incrementPatch = ( ptch , pre ) : number => pre . length === 0 ? ptch + 1 : ptch ; const increment = ( from , to ) : string => { const parsed = parse ( from ) ; const { major : maj , prerelease : pre } = parsed ; let { minor : min , patch : ptch } = parsed ; min = min || 0 ; ptch = ptch || 0 ; let nextVersion ; const adapted = adapt ( to , from ) ; if ( eq ( from , adapted ) ) { return incrementLastSegment ( from ) ; } const isStable = ( x ) : boolean => regEx ( /^[0-9.-/]+$/ ) . test ( x ) ; if ( major ( from ) !== major ( adapted ) ) { nextVersion = [ incrementMajor ( maj , min , ptch , pre ?? [ ] ) , 0 , 0 ] . join ( '.' ) ; } else if ( minor ( from ) !== minor ( adapted ) ) { nextVersion = [ maj , incrementMinor ( min , ptch , pre ?? [ ] ) , 0 ] . join ( '.' ) ; } else if ( patch ( from ) !== patch ( adapted ) ) { nextVersion = [ maj , min , incrementPatch ( ptch , pre ?? [ ] ) ] . join ( '.' ) ; } else if ( isStable ( from ) && isStable ( adapted ) ) { nextVersion = [ maj , min , incrementPatch ( ptch , pre ?? [ ] ) ] . join ( '.' ) ; } else { nextVersion = [ maj , min , ptch ] . join ( '.' ) ; } return increment ( nextVersion , to ) ; } ; const decrement = ( version ) : string => { const segments = releaseSegments ( version ) ; const nextSegments = segments . reverse ( ) . reduce ( ( accumulator , segment , index ) : number [ ] => { if ( index === 0 ) { return [ ( segment as number ) - 1 ] ; } if ( accumulator [ index - 1 ] === - 1 ) { return [ ... accumulator . slice ( 0 , index - 1 ) , 0 , ( segment as number ) - 1 , ] ; } return [ ... accumulator , segment as number ] ; } , [ ] ) ; return nextSegments . reverse ( ) . join ( '.' ) ; } ; export { parse , floor , increment , decrement } ;