@@ -5,20 +5,29 @@ mod repo;
55mod utils;
66
77use core:: str;
8- use std:: path:: { Path , PathBuf } ;
8+ use std:: {
9+ fs:: File ,
10+ io:: Write ,
11+ path:: { Path , PathBuf } ,
12+ } ;
913
1014use git2:: Repository ;
11- use serde:: Deserialize ;
15+ use serde:: { Deserialize , Serialize } ;
1216use snafu:: { OptionExt , ResultExt as _, Snafu } ;
1317use tracing_subscriber:: { layer:: SubscriberExt as _, util:: SubscriberInitExt as _} ;
1418
1519#[ derive( clap:: Parser ) ]
1620struct ProductVersion {
21+ /// The product name slug (such as druid)
1722 product : String ,
23+
24+ /// The product version (such as 28.0.0)
25+ ///
26+ /// Should not contain a v prefix.
1827 version : String ,
1928}
2029
21- #[ derive( Deserialize ) ]
30+ #[ derive( Deserialize , Serialize ) ]
2231struct ProductVersionConfig {
2332 upstream : String ,
2433 base : String ,
@@ -101,6 +110,22 @@ enum Cmd {
101110 #[ clap( flatten) ]
102111 pv : ProductVersion ,
103112 } ,
113+
114+ /// Creates a patchable.toml for a given product version
115+ Init {
116+ #[ clap( flatten) ]
117+ pv : ProductVersion ,
118+
119+ /// The upstream URL (such as https://github.com/apache/druid.git)
120+ #[ clap( long) ]
121+ upstream : String ,
122+
123+ /// The upstream commit-ish (such as druid-28.0.0) that the patch series applies to
124+ ///
125+ /// Refs (such as tags and branches) will be resolved to commit IDs.
126+ #[ clap( long) ]
127+ base : String ,
128+ } ,
104129}
105130
106131#[ derive( Debug , Snafu ) ]
@@ -118,6 +143,18 @@ pub enum Error {
118143 source : toml:: de:: Error ,
119144 path : PathBuf ,
120145 } ,
146+ #[ snafu( display( "failed to serialize config" ) ) ]
147+ SerializeConfig { source : toml:: ser:: Error } ,
148+ #[ snafu( display( "failed to create patch dir at {path:?}" ) ) ]
149+ CreatePatchDir {
150+ source : std:: io:: Error ,
151+ path : PathBuf ,
152+ } ,
153+ #[ snafu( display( "failed to save config to {path:?}" ) ) ]
154+ SaveConfig {
155+ source : std:: io:: Error ,
156+ path : PathBuf ,
157+ } ,
121158
122159 #[ snafu( display( "failed to find images repository" ) ) ]
123160 FindImagesRepo { source : git2:: Error } ,
@@ -208,7 +245,7 @@ fn main() -> Result<()> {
208245 . context ( OpenProductRepoForCheckoutSnafu ) ?;
209246
210247 let base_commit =
211- repo:: ensure_commit_exists_or_fetch ( & product_repo, & config. base , & config. upstream )
248+ repo:: resolve_commitish_or_fetch ( & product_repo, & config. base , & config. upstream )
212249 . context ( FetchBaseCommitSnafu ) ?;
213250 let patched_commit = patch:: apply_patches ( & product_repo, & ctx. patch_dir ( ) , base_commit)
214251 . context ( ApplyPatchesSnafu ) ?;
@@ -228,6 +265,7 @@ fn main() -> Result<()> {
228265 "worktree is ready!"
229266 ) ;
230267 }
268+
231269 Cmd :: Export { pv } => {
232270 let ctx = ProductVersionContext {
233271 pv,
@@ -288,6 +326,40 @@ fn main() -> Result<()> {
288326 "worktree is exported!"
289327 ) ;
290328 }
329+
330+ Cmd :: Init { pv, upstream, base } => {
331+ let ctx = ProductVersionContext {
332+ pv,
333+ images_repo_root,
334+ } ;
335+
336+ let product_repo_root = ctx. repo ( ) ;
337+ let product_repo = tracing:: info_span!(
338+ "finding product repository" ,
339+ product. repository = ?product_repo_root,
340+ )
341+ . in_scope ( || repo:: ensure_bare_repo ( & product_repo_root) )
342+ . context ( OpenProductRepoForCheckoutSnafu ) ?;
343+
344+ tracing:: info!( ?base, "resolving base commit-ish" ) ;
345+ let base_commit = repo:: resolve_commitish_or_fetch ( & product_repo, & base, & upstream)
346+ . context ( FetchBaseCommitSnafu ) ?;
347+ tracing:: info!( ?base, base. commit = ?base_commit, "resolved base commit" ) ;
348+
349+ let config = ProductVersionConfig {
350+ upstream,
351+ base : base. to_string ( ) ,
352+ } ;
353+ let config_path = ctx. config_path ( ) ;
354+ if let Some ( config_dir) = config_path. parent ( ) {
355+ std:: fs:: create_dir_all ( config_dir)
356+ . context ( CreatePatchDirSnafu { path : config_dir } ) ?;
357+ }
358+ let config_toml = toml:: to_string_pretty ( & config) . context ( SerializeConfigSnafu ) ?;
359+ File :: create_new ( & config_path)
360+ . and_then ( |mut f| f. write_all ( config_toml. as_bytes ( ) ) )
361+ . context ( SaveConfigSnafu { path : config_path } ) ?;
362+ }
291363 }
292364
293365 Ok ( ( ) )
0 commit comments