/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 2 1 ĠHERE ĠEurope ĠB . V . Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 2 1 ĠB os ch . IO ĠGmbH Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠ Ġhttps :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ* Ċ Ġ* ĠSPDX - License - Identifier : ĠApache - 2 . 0 Ċ Ġ* ĠLicense - Filename : ĠLICENSE Ċ Ġ*/ Ċ Ċ package Ġorg . oss review toolkit . scanner . experimental Ċ Ċ import Ġjava . io . IOException Ċ import Ġjava . net . Http URLConnection Ċ Ċ import Ġkotlinx . coroutines . run Blocking Ċ Ċ import Ġokhttp 3 . Request Ċ Ċ import Ġorg . oss review toolkit . model . Artifact Provenance Ċ import Ġorg . oss review toolkit . model . Known Provenance Ċ import Ġorg . oss review toolkit . model . Package Ċ import Ġorg . oss review toolkit . model . Provenance Ċ import Ġorg . oss review toolkit . model . Remote Artifact Ċ import Ġorg . oss review toolkit . model . Repository Provenance Ċ import Ġorg . oss review toolkit . model . Source Code Origin Ċ import Ġorg . oss review toolkit . model . V cs Info Ċ import Ġorg . oss review toolkit . utils . common . collect Messages AsString Ċ import Ġorg . oss review toolkit . utils . core . Ok HttpClient Helper Ċ import Ġorg . oss review toolkit . utils . core . log Ċ import Ġorg . oss review toolkit . utils . core . show StackTrace Ċ Ċ /** Ċ Ġ* ĠThe Ġ[ Package Provenance Resolver ] Ġprovides Ġa Ġfunction Ġto Ġresolve Ġthe Ġ[ Provenance ] Ġof Ġa Ġ[ Package ]. Ċ Ġ*/ Ċ interface ĠPackage Provenance Resolver Ġ{ ĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠResolve Ġthe Ġ[ Known Provenance ] Ġof Ġ[ pkg ] Ġbased Ġon Ġthe Ġprovided Ġ[ sourceCode Origin Priority ]. ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠThrows Ġan Ġ[ IOException ] Ġif Ġthe Ġpro venance Ġcannot Ġbe Ġresolved . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġresolve Provenance ( pkg : ĠPackage , Ġsource Code Origin Priority : ĠList < Source Code Origin >): ĠKnown Provenance Ċ } Ċ Ċ /** Ċ Ġ* ĠThe Ġdefault Ġimplementation Ġof Ġ[ Package Provenance Resolver ]. Ċ Ġ*/ Ċ class ĠDefault Package Provenance Resolver ( ĊĠĠĠ Ġprivate Ġval Ġstorage : ĠPackage Provenance Storage , ĊĠĠĠ Ġprivate Ġval Ġworking Tree Cache : ĠWorking Tree Cache Ċ ) Ġ: ĠPackage Provenance Resolver Ġ{ ĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠResolve Ġthe Ġ[ Provenance ] Ġof Ġ[ pkg ] Ġbased Ġon Ġthe Ġprovided Ġ[ sourceCode Origin Priority ]. ĠFor Ġsource Ġartifacts Ġit Ġis ĊĠĠĠĠ Ġ* Ġverified Ġthat Ġthe Ġ[ Remote Artifact ] Ġdoes Ġexist . ĠFor Ġa ĠV CS Ġit Ġis Ġverified Ġthat Ġthe Ġrevision Ġexists . ĠIf Ġthe Ġrevision ĊĠĠĠĠ Ġ* Ġprovided Ġby Ġthe Ġ[ package ][ pkg ] Ġmetadata Ġdoes Ġnot Ġexist Ġor Ġis Ġmissing , Ġthe Ġfunction Ġtries Ġto Ġguess Ġthe Ġtag Ġbased ĊĠĠĠĠ Ġ* Ġon Ġthe Ġname Ġand Ġversion Ġof Ġthe Ġ[ package ][ pkg ]. ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġfun Ġresolve Provenance ( pkg : ĠPackage , Ġsource Code Origin Priority : ĠList < Source Code Origin >): ĠKnown Provenance Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġerrors Ġ= Ġmutable Map Of < Source Code Origin , ĠThrowable >() ĊĊĠĠĠĠĠĠĠ Ġsource Code Origin Priority . forEach Ġ{ Ġsource Code Origin Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrun Catch ing Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( sourceCode Origin ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSource Code Origin . AR TI FACT Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( pkg . source Artifact Ġ!= ĠRemote Artifact . EMPTY ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġresolve Source Artifact ( pkg ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSource Code Origin . V CS Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( pkg . vcs Processed Ġ!= ĠV cs Info . EMPTY ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġrun Blocking Ġ{ Ġresolve V cs ( pkg ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. on Failure Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . show StackTrace () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġerrors [ sourceCode Origin ] Ġ= Ġit ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Could Ġnot Ġresolve Ġ$ sourceCode Origin Ġfor Ġ${ pkg . id . to Coordinates ()} : Ġ${ it . collect Messages AsString () }" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġmessage Ġ= Ġbuild String Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġappend ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Could Ġnot Ġresolve Ġpro venance Ġfor Ġ${ pkg . id . to Coordinates ()} Ġfor Ġsource Ġcode Ġorig ins Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"$ sourceCode Origin Priority ." ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġerrors . forEach Ġ{ Ġ( origin , Ġthrowable ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġappend ("\ n Resolution Ġof Ġ$ origin Ġfailed Ġwith :\ n ${ throwable . collect Messages AsString () }") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġlog . info Ġ{ Ġmessage Ġ} ĊĊĠĠĠĠĠĠĠ Ġthrow ĠIOException ( message ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġresolve Source Artifact ( pkg : ĠPackage ): ĠArtifact Provenance Ġ{ ĊĠĠĠĠĠĠĠ Ġwhen Ġ( val Ġstored Result Ġ= Ġstorage . read Provenance ( pkg . id , Ġpkg . source Artifact )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠResolved Artifact Provenance Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Found Ġa Ġstored Ġartifact Ġresolution Ġfor Ġpackage Ġ${ pkg . id . to Coordinates ()} ." ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġstored Result . pro venance ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠUn resolved Package Provenance Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Found Ġa Ġstored Ġartifact Ġresolution Ġfor Ġpackage Ġ${ pkg . id . to Coordinates ()} Ġwhich Ġfailed Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" previous ly . ĠNot Ġattempting Ġresolution Ġagain . ĠThe Ġerror Ġwas : Ġ${ stored Result . message }" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException ( stored Result . message ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Could Ġnot Ġfind Ġa Ġstored Ġartifact Ġresolution Ġresult Ġfor Ġpackage Ġ${ pkg . id . to Coordinates () }," Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" at tempting Ġresolution ." ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġrequest Ġ= ĠRequest . Builder (). head (). url ( pkg . source Artifact . url ). build () ĊĠĠĠĠĠĠĠ ĠOk HttpClient Helper . execute ( request ). use Ġ{ Ġresponse Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( response . code Ġ== ĠHttp URLConnection . HTTP _ OK ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġartifact Provenance Ġ= ĠArtifact Provenance ( pkg . source Artifact ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstorage . put Provenance ( pkg . id , Ġpkg . source Artifact , ĠResolved Artifact Provenance ( artifact Provenance )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġartifact Provenance ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" Could Ġnot Ġverify Ġexistence Ġof Ġsource Ġartifact Ġat Ġ${ pkg . source Artifact . url }. ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġresolve V cs ( pkg : ĠPackage ): ĠRepository Provenance Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠTODO : ĠCurrently Ġthe Ġcommit Ġrevision Ġis Ġresolved Ġby Ġchecking Ġout Ġthe Ġprovided Ġrevision . ĠThere Ġare Ġprobably ĊĠĠĠĠĠĠĠ Ġ// ĠĠĠĠĠĠ Ġprobably Ġmore Ġefficient Ġways Ġto Ġdo Ġthis Ġdepending Ġon Ġthe ĠV CS , Ġespecially Ġfor Ġproviders Ġlike ĠGitHub ĊĠĠĠĠĠĠĠ Ġ// ĠĠĠĠĠĠ Ġor ĠGitLab Ġwhich Ġprovide Ġan ĠAPI . ĊĊĠĠĠĠĠĠĠ Ġwhen Ġ( val Ġstored Result Ġ= Ġstorage . read Provenance ( pkg . id , Ġpkg . vcs Processed )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠResolved Repository Provenance Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( stored Result . is Fixed Revision ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Found Ġa Ġstored Ġrepository Ġresolution Ġfor Ġpackage Ġ${ pkg . id . to Coordinates ()} Ġwith Ġthe Ġfixed Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" revision Ġ${ stored Result . cloned Revision } Ġwhich Ġwas Ġresolved Ġto Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ stored Result . pro venance . resolved Revision } ." ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġstored Result . pro venance ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Found Ġa Ġstored Ġrepository Ġresolution Ġresult Ġfor Ġpackage Ġ${ pkg . id . to Coordinates ()} Ġwith Ġthe Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" non - fixed Ġrevision Ġ${ stored Result . cloned Revision } Ġwhich Ġwas Ġresolved Ġto Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ stored Result . pro venance . resolved Revision }. ĠRe starting Ġresolution Ġof Ġthe Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" non - fixed Ġrevision ." ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠUn resolved Package Provenance Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Found Ġa Ġstored Ġrepository Ġresolution Ġresult Ġfor Ġpackage Ġ${ pkg . id . to Coordinates ()} Ġwhich Ġfailed Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" previous ly . ĠNot Ġattempting Ġresolution Ġagain . ĠThe Ġerror Ġwas : Ġ${ stored Result . message }" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException ( stored Result . message ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Could Ġnot Ġfind Ġa Ġstored Ġrepository Ġresolution Ġresult Ġfor Ġpackage Ġ${ pkg . id . to Coordinates () }," Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" at tempting Ġresolution ." ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġworking Tree Cache . use ( pkg . vcs Processed ) Ġ{ Ġv cs , Ġworking Tree Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrevision Candidates Ġ= Ġrun Catch ing Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġv cs . get Revision Candidates ( working Tree , Ġpkg , Ġallow Moving Re visions Ġ= Ġtrue ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. get OrDefault ( empty Set ()) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( revision Candidates . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmessage Ġ= Ġ" Could Ġnot Ġfind Ġany Ġrevision Ġcandidates Ġfor Ġpackage Ġ${ pkg . id . to Coordinates ()} Ġwith ĠV CS Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ pkg . vcs Processed } ." ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstorage . put Provenance ( pkg . id , Ġpkg . vcs Processed , ĠUn resolved Package Provenance ( message )) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException ( message ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġrevision Candidates . forEach Indexed Ġ{ Ġindex , Ġrevision Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info Ġ{ Ġ" Trying Ġrevision Ġcandidate Ġ'$ revision ' Ġ(${ index Ġ+ Ġ 1 } Ġof Ġ${ revision Candidates . size }). " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġv cs . update Working Tree ( working Tree , Ġrevision , Ġpkg . vcs Processed . path , Ġrecursive Ġ= Ġfalse ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( result . is Success ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresolved Revision Ġ= Ġworking Tree . get Revision () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Resolved Ġrevision Ġfor Ġpackage Ġ${ pkg . id . to Coordinates ()} Ġto Ġ$ resolved Revision Ġbased Ġon Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" g ues sed Ġrevision Ġ$ revision ." ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrepository Provenance Ġ= ĠRepository Provenance ( pkg . vcs Processed , Ġworking Tree . get Revision ()) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstorage . put Provenance ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpkg . id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpkg . vcs Processed , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠResolved Repository Provenance ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrepository Provenance , Ġrevision , Ġv cs . is Fixed Revision ( working Tree , Ġrevision ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ use Ġrepository Provenance ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmessage Ġ= Ġ" Could Ġnot Ġresolve Ġany Ġof Ġthe Ġrevision Ġcandidates Ġ$ revision Candidates Ġfor Ġpackage Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ pkg . id . to Coordinates ()} Ġwith ĠV CS Ġ${ pkg . vcs Processed } ." ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġstorage . put Provenance ( pkg . id , Ġpkg . vcs Processed , ĠUn resolved Package Provenance ( message )) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException ( message ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ