33namespace CodedMonkey \Dirigent \Package ;
44
55use CodedMonkey \Dirigent \Composer \ComposerClient ;
6+ use CodedMonkey \Dirigent \Composer \ConfigFactory ;
67use CodedMonkey \Dirigent \Doctrine \Entity \Version ;
8+ use Composer \IO \NullIO ;
9+ use Composer \Pcre \Preg ;
10+ use Composer \Util \Filesystem as ComposerFilesystem ;
11+ use Composer \Util \Git as GitUtility ;
12+ use Composer \Util \ProcessExecutor ;
13+ use Composer \Util \Url ;
714use Symfony \Component \DependencyInjection \Attribute \Autowire ;
815use Symfony \Component \Filesystem \Filesystem ;
916
1017readonly class PackageDistributionResolver
1118{
1219 private Filesystem $ filesystem ;
13- private string $ storagePath ;
20+ private string $ distributionStoragePath ;
1421
1522 public function __construct (
1623 private ComposerClient $ composer ,
24+ #[Autowire(param: 'dirigent.dist_builder.enabled ' )]
25+ private bool $ buildDistributions ,
26+ #[Autowire(param: 'dirigent.dist_builder.dev_packages ' )]
27+ private bool $ buildDevDistributions ,
1728 #[Autowire(param: 'dirigent.storage.path ' )]
1829 string $ storagePath ,
1930 ) {
2031 $ this ->filesystem = new Filesystem ();
21- $ this ->storagePath = "$ storagePath/distribution " ;
32+ $ this ->distributionStoragePath = "$ storagePath/distribution " ;
2233 }
2334
2435 public function exists (string $ packageName , string $ packageVersion , string $ reference , string $ type ): bool
@@ -28,7 +39,7 @@ public function exists(string $packageName, string $packageVersion, string $refe
2839
2940 public function path (string $ packageName , string $ packageVersion , string $ reference , string $ type ): string
3041 {
31- return "{ $ this ->storagePath } / { $ packageName} / { $ packageVersion} - { $ reference} . { $ type} " ;
42+ return "$ this ->distributionStoragePath / $ packageName/ $ packageVersion- $ reference. $ type " ;
3243 }
3344
3445 public function resolve (Version $ version , string $ reference , string $ type ): bool
@@ -41,17 +52,76 @@ public function resolve(Version $version, string $reference, string $type): bool
4152 return true ;
4253 }
4354
44- if ($ reference !== $ version ->getDistReference () || $ type !== $ version ->getDistType ()) {
55+ if (
56+ null === $ version ->getDist ()
57+ && $ this ->buildDistributions
58+ && (!$ version ->isDevelopment () || $ this ->buildDevDistributions )
59+ ) {
60+ return $ this ->build ($ version , $ reference , $ type );
61+ } elseif (null !== $ version ->getDist ()) {
62+ return $ this ->mirror ($ version , $ reference , $ type );
63+ }
64+
65+ return false ;
66+ }
67+
68+ private function build (Version $ version , string $ reference , string $ type ): bool
69+ {
70+ // Skip building of outdated references for now
71+ if ($ reference !== $ version ->getSourceReference ()) {
72+ return false ;
73+ }
74+
75+ // Only provide .zip support for now
76+ if ('zip ' !== $ type ) {
77+ return false ;
78+ }
79+
80+ $ package = $ version ->getPackage ();
81+ $ repositoryUrl = $ package ->getRepositoryUrl ();
82+ $ distributionPath = $ this ->path ($ package ->getName (), $ version ->getNormalizedVersion (), $ reference , $ type );
83+
84+ $ composerConfig = ConfigFactory::createForVcsRepository ($ repositoryUrl , $ package ->getRepositoryCredentials ());
85+
86+ $ gitUtility = new GitUtility (
87+ $ io = new NullIO (),
88+ $ composerConfig ,
89+ $ process = new ProcessExecutor ($ io ),
90+ new ComposerFilesystem ($ process ),
91+ );
92+
93+ $ cacheRepositoryName = Preg::replace ('{[^a-z0-9.]}i ' , '- ' , Url::sanitize ($ repositoryUrl ));
94+ $ cachePath = $ composerConfig ->get ('cache-vcs-dir ' ) . '/ ' . $ cacheRepositoryName . '/ ' ;
95+
96+ $ this ->filesystem ->mkdir (dirname ($ distributionPath ));
97+
98+ $ gitUtility ->runCommands ([
99+ ['git ' , 'archive ' , '--format=zip ' , "--output= $ distributionPath " , $ reference ],
100+ ], $ repositoryUrl , $ cachePath );
101+
102+ return true ;
103+ }
104+
105+ private function mirror (Version $ version , string $ reference , string $ type ): bool
106+ {
107+ // Skip mirroring of outdated references for now
108+ if ($ reference !== $ version ->getDistReference ()) {
109+ return false ;
110+ }
111+
112+ // The distribution type must match the origin format
113+ if ($ type !== $ version ->getDistType ()) {
45114 return false ;
46115 }
47116
48- $ distUrl = $ version ->getDistUrl ();
49- $ path = $ this ->path ($ packageName , $ packageVersion , $ reference , $ type );
117+ $ package = $ version ->getPackage ();
118+ $ distributionUrl = $ version ->getDistUrl ();
119+ $ distributionPath = $ this ->path ($ package ->getName (), $ version ->getNormalizedVersion (), $ reference , $ type );
50120
51- $ this ->filesystem ->mkdir (dirname ($ path ));
121+ $ this ->filesystem ->mkdir (dirname ($ distributionPath ));
52122
53123 $ httpDownloader = $ this ->composer ->createHttpDownloader ();
54- $ httpDownloader ->copy ($ distUrl , $ path );
124+ $ httpDownloader ->copy ($ distributionUrl , $ distributionPath );
55125
56126 return true ;
57127 }
0 commit comments