def build_cmd(force: bool) -> None: """Build a static site based on current state.""" output_dir = build_path output_dir.mkdir(parents=True, exist_ok=True) click.echo(f"Building site to {output_dir}...", err=True) design_dir = Path(entrypoint) / "design" cfg = config.load() with upload.client(cfg, break_lock=force) as client: try: pxl_state_json = upload.get_json(client, "state.json") overview = state.Overview.from_json(pxl_state_json) assert overview is not None, "Expected state to be valid" except client.boto.exceptions.NoSuchKey as e: click.echo( "Remote state not found. Please upload before continuing.", err=True ) sys.exit(1) except Exception as e: click.echo(e, err=True) sys.exit(1) bucket_puburl = f"https://{cfg.s3_bucket}.{cfg.s3_region}.{cfg.s3_endpoint}" generate.build( overview=overview, output_dir=output_dir, template_dir=design_dir, bucket_puburl=bucket_puburl, public_image_url=cfg.public_image_url, ) click.echo("Done.", err=True)
def upload_cmd(dir_name: str, force: bool) -> None: """ Upload a directory to the photo hosting. """ cfg = config.load() dir_path = Path(dir_name) if not dir_path.is_dir(): click.echo(f"{dir_path} is not a directory.", err=True) sys.exit(1) with upload.client(cfg, break_lock=force) as client: album_name = click.prompt( "What name should the album have?", default=dir_path.name.title() ) try: pxl_state_json = upload.get_json(client, "state.json") pxl_state = state.Overview.from_json(pxl_state_json) assert pxl_state is not None, "Expected state to be valid" except client.boto.exceptions.NoSuchKey as e: pxl_state = state.Overview.empty() except Exception as e: print(e) sys.exit(1) print(pxl_state) # Get existing album with this name for appending. album = pxl_state.get_album_by_name(album_name) if album: click.confirm("Album already exists. Add to existing album?", abort=True) else: click.echo("Creating new album.", err=True) album = state.Album( name_display=album_name, name_nav=album_name.lower().replace(" ", "-"), created=datetime.datetime.now(), images=[], ) # Find all files with known JPEG extensions. We don't # traverse nested directories, just the toplevel. for entry in dir_path.iterdir(): if not entry.is_file(): continue if not entry.suffix.lower() in [".jpeg", ".jpg"]: continue image = upload.public_image_with_size(client, entry) album = album.add_image(image) pxl_state = pxl_state.add_or_replace_album(album) upload.private_json(client, json.dumps(pxl_state.to_json()), "state.json")
def edit_cmd(album_name: str, force: bool) -> None: """ Edit the name and date of an album """ cfg = config.load() with upload.client(cfg, break_lock=force) as client: try: pxl_state_json = upload.get_json(client, "state.json") pxl_state = state.Overview.from_json(pxl_state_json) assert pxl_state is not None, "Expected state to be valid" except client.boto.exceptions.NoSuchKey as e: pxl_state = state.Overview.empty() except Exception as e: print(e) sys.exit(1) print(pxl_state) old_album = pxl_state.get_album_by_name(album_name) if not (old_album): click.echo(f"{album_name} does not exist", err=True) sys.exit(1) else: new_album = copy.deepcopy(old_album) album_name = click.prompt("What should the new album name be?", default=old_album.name_display) album_date = click.prompt( # type: ignore "What should the new album date be?", default=str(old_album.created), value_proc=validate, ) alt_album = pxl_state.get_album_by_name(album_name) if alt_album and not (album_name == old_album.name_display): click.confirm( "An album with that name already exists. Merge albums?", abort=True) alt_album.created = album_date alt_album.images = alt_album.images + old_album.images pxl_state = pxl_state.remove_album(old_album) pxl_state = pxl_state.edit_album(alt_album, alt_album) upload.private_json(client, json.dumps(pxl_state.to_json()), "state.json") else: new_album.name_display = album_name new_album.name_nav = album_name.lower().replace(" ", "-") new_album.created = album_date pxl_state = pxl_state.edit_album(old_album, new_album) upload.private_json(client, json.dumps(pxl_state.to_json()), "state.json")
def deploy_cmd() -> None: """Deploy the static output.""" if not config.is_initialized(): click.echo("Config not initialized. Please run `pxl init` first.", err=False) sys.exit(1) output_dir = build_path if not output_dir.is_dir(): click.echo("No output to deploy. Please run `pxl build` first.", err=False) sys.exit(1) cfg = config.load() deploy_command = [ "rsync", "-rzP", "--delete", f"{output_dir}/", f"{cfg.deploy_user}@{cfg.deploy_host}:{cfg.deploy_path}", ] subprocess.run(deploy_command)
def delete_cmd(album_name: str, force: bool) -> None: """ Delete an album and its pictures. """ cfg = config.load() with upload.client(cfg, break_lock=force) as client: try: pxl_state_json = upload.get_json(client, "state.json") pxl_state = state.Overview.from_json(pxl_state_json) assert pxl_state is not None, "Expected state to be valid" except client.boto.exceptions.NoSuchKey as e: pxl_state = state.Overview.empty() except Exception as e: print(e) sys.exit(1) print(pxl_state) # Get existing album with this name to check if it exists album = pxl_state.get_album_by_name(album_name) if album: click.echo("Album found, deleting pictures...") for image in album.images: upload.delete_image(client, image.get_name("original")) upload.delete_image(client, image.get_name("display_w_1600")) upload.delete_image(client, image.get_name("thumbnail_w_400")) else: click.echo("Given album not found") sys.exit(1) click.echo("deleting album...") pxl_state = pxl_state.remove_album(album) upload.private_json(client, json.dumps(pxl_state.to_json()), "state.json") click.echo("deleted album, please run build and deploy now")
def deploy_cmd() -> None: """Deploy the static output.""" if not config.is_initialized(): click.echo("Config not initialized. Please run `pxl init` first.", err=False) sys.exit(1) output_dir = build_path if not output_dir.is_dir(): click.echo("No output to deploy. Please run `pxl build` first.", err=False) sys.exit(1) cfg = config.load() dry_run_result = subprocess.run( build_deploy_rsync(output_dir, cfg, dry_run=True), capture_output=True, text=True, ) # Inspect dry run output to check whether there are any files to delete if len(dry_run_result.stdout) > 0: stdout_lines = dry_run_result.stdout.split("\n") click.echo( click.style( "Warning! Rsync reports that it will delete these files:", fg="yellow")) for line in stdout_lines[:-1]: parts = line.split(" ", 1) click.echo(click.style(parts[1], fg="yellow")) if not click.confirm("Continue?"): click.echo("Aborting.") return dry_run_result = subprocess.run( build_deploy_rsync(output_dir, cfg, dry_run=False))