@@ -3203,6 +3203,60 @@ def test_command(args: argparse.Namespace) -> None:
3203
3203
unittest .main (argv = [__file__ , * args .unittest_args ])
3204
3204
3205
3205
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
+
3206
3260
def main () -> None :
3207
3261
parser = argparse .ArgumentParser (prog = "scrapscript" )
3208
3262
subparsers = parser .add_subparsers (dest = "command" )
@@ -3226,6 +3280,16 @@ def main() -> None:
3226
3280
apply .add_argument ("program" )
3227
3281
apply .add_argument ("--debug" , action = "store_true" )
3228
3282
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
+
3229
3293
args = parser .parse_args ()
3230
3294
if not args .command :
3231
3295
args .debug = False
0 commit comments