@@ -3203,6 +3203,60 @@ def test_command(args: argparse.Namespace) -> None:
32033203 unittest .main (argv = [__file__ , * args .unittest_args ])
32043204
32053205
3206+ class ScrapError (Exception ):
3207+ pass
3208+
3209+
3210+ def _ensure_pygit2 () -> ModuleType :
3211+ try :
3212+ import pygit2
3213+
3214+ assert isinstance (pygit2 , ModuleType )
3215+ return pygit2
3216+ except ImportError :
3217+ raise ScrapError ("Please install pygit2 to work with scrapyards" )
3218+
3219+
3220+ def yard_init_command (args : argparse .Namespace ) -> None :
3221+ git = _ensure_pygit2 ()
3222+ repo = git .init_repository (args .directory , bare = True )
3223+ if not repo .is_empty :
3224+ raise ScrapError ("Scrapyard already initialized; cannot init scrapyard again" )
3225+ # Make an initial commit so that all other commands can do the normal
3226+ # commit flow
3227+ # TODO(max): Settle on an agreed-upon branch name like 'trunk'
3228+ ref = "HEAD"
3229+ author = repo .default_signature
3230+ # Make an empty tree
3231+ tree_id = repo .TreeBuilder ().write ()
3232+ message = "Initialize scrapyard"
3233+ parents : object = []
3234+ repo .create_commit (ref , author , author , message , tree_id , parents )
3235+
3236+
3237+ def yard_commit_command (args : argparse .Namespace ) -> None :
3238+ git = _ensure_pygit2 ()
3239+ # Find the scrapyard
3240+ repo_path = git .discover_repository (args .yard )
3241+ if repo_path is None :
3242+ raise ScrapError (f"Please create a scrapyard; { args .yard !r} is not initialized" )
3243+ repo = git .Repository (repo_path , git .GIT_REPOSITORY_OPEN_BARE )
3244+ result = eval_exp (STDLIB , parse (tokenize (args .program_file .read ())))
3245+ serialized = serialize (result )
3246+ # Make a git tree
3247+ root = repo .TreeBuilder ()
3248+ obj_id = repo .create_blob (serialized )
3249+ # TODO(max): Figure out how to handle names like a/b; make directories?
3250+ root .insert (args .scrap_name , obj_id , git .GIT_FILEMODE_BLOB )
3251+ tree_id = root .write ()
3252+ # Commit the tree
3253+ ref = repo .head .name
3254+ author = repo .default_signature
3255+ message = f"Update { args .scrap_name } "
3256+ parents = [repo .head .target ]
3257+ repo .create_commit (ref , author , author , message , tree_id , parents )
3258+
3259+
32063260def main () -> None :
32073261 parser = argparse .ArgumentParser (prog = "scrapscript" )
32083262 subparsers = parser .add_subparsers (dest = "command" )
@@ -3226,6 +3280,16 @@ def main() -> None:
32263280 apply .add_argument ("program" )
32273281 apply .add_argument ("--debug" , action = "store_true" )
32283282
3283+ yard = subparsers .add_parser ("yard" ).add_subparsers (dest = "command" , required = True )
3284+ yard_init = yard .add_parser ("init" )
3285+ yard_init .set_defaults (func = yard_init_command )
3286+ yard_init .add_argument ("directory" )
3287+ yard_commit = yard .add_parser ("commit" )
3288+ yard_commit .set_defaults (func = yard_commit_command )
3289+ yard_commit .add_argument ("yard" )
3290+ yard_commit .add_argument ("scrap_name" )
3291+ yard_commit .add_argument ("program_file" , type = argparse .FileType ("r" ))
3292+
32293293 args = parser .parse_args ()
32303294 if not args .command :
32313295 args .debug = False
0 commit comments