Skip to content

Commit ede3a26

Browse files
committed
Implement scrap yard init/commit
Use pygit2 and store scrapyards as git repositories. Scraps are blobs/files (for now? maybe they should be trees if they refer to other scraps). The representation on-disk is the serialized result of evaluating the scrap.
1 parent 4114365 commit ede3a26

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

scrapscript.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
32063260
def 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

Comments
 (0)