Fix record command funky timekeeping
This commit is contained in:
parent
e76489b1c0
commit
c3dd418c8c
@ -6,6 +6,7 @@ from .. import store
|
|||||||
from .common import confirm
|
from .common import confirm
|
||||||
from .diff import print_diff
|
from .diff import print_diff
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from typing import Any, Optional, Union
|
from typing import Any, Optional, Union
|
||||||
@ -21,6 +22,7 @@ def record(
|
|||||||
skip_confirm: bool = False,
|
skip_confirm: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Unwrapped record command"""
|
"""Unwrapped record command"""
|
||||||
|
start_time = datetime.now()
|
||||||
|
|
||||||
if store_path is None:
|
if store_path is None:
|
||||||
curdir = os.path.realpath(os.getcwd())
|
curdir = os.path.realpath(os.getcwd())
|
||||||
@ -36,21 +38,34 @@ def record(
|
|||||||
else: # this is an existing store
|
else: # this is an existing store
|
||||||
s = store.Store(store_path)
|
s = store.Store(store_path)
|
||||||
|
|
||||||
fsdiff = s.diff()
|
with s.new_program("RECORD", message) as p:
|
||||||
|
p.start_time = start_time # reset start to actual start of command
|
||||||
|
with s.committing() as cur: # entire record operation should be one transaction
|
||||||
|
# create a task for this operation
|
||||||
|
task = p.new_task(name="Store._record_recursive", cur=cur)
|
||||||
|
|
||||||
if show_diff:
|
fsdiff = s.diff()
|
||||||
print_diff(fsdiff, show_hashes=show_hashes, use_color=use_color)
|
|
||||||
|
|
||||||
logger.info("Recording with message: {}", message)
|
if show_diff:
|
||||||
|
print_diff(fsdiff, show_hashes=show_hashes, use_color=use_color)
|
||||||
|
|
||||||
if skip_confirm or confirm("Record the values above into the database?"):
|
logger.info("Recording with message: {}", message)
|
||||||
s.record(fsdiff, message=message)
|
|
||||||
else:
|
if skip_confirm or confirm(f"Record to {s.db_path}?"):
|
||||||
logger.info("Cancelled!")
|
# descend the diff, tracking parent filedir IDs, creating them and
|
||||||
sys.exit(1)
|
# recording new versions of each, when necessary
|
||||||
|
fsdiff.persist(cur=cur, source_task=task)
|
||||||
|
else:
|
||||||
|
logger.info("Cancelled!")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
|
@click.option(
|
||||||
|
"--no-show",
|
||||||
|
is_flag=True,
|
||||||
|
help="Do not show what is about to be recorded.",
|
||||||
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"-H",
|
"-H",
|
||||||
"--show-hashes",
|
"--show-hashes",
|
||||||
@ -62,6 +77,12 @@ def record(
|
|||||||
is_flag=True,
|
is_flag=True,
|
||||||
help="If given, do not print any color output.",
|
help="If given, do not print any color output.",
|
||||||
)
|
)
|
||||||
|
@click.option(
|
||||||
|
"-y",
|
||||||
|
"--yes",
|
||||||
|
is_flag=True,
|
||||||
|
help="Do not ask for confirmation.",
|
||||||
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"-m",
|
"-m",
|
||||||
"--message",
|
"--message",
|
||||||
@ -78,7 +99,14 @@ def record(
|
|||||||
"of given paths. If given the path to a non-store directory, a new "
|
"of given paths. If given the path to a non-store directory, a new "
|
||||||
"store is initialized there.",
|
"store is initialized there.",
|
||||||
)
|
)
|
||||||
def record_cli(show_hashes: bool, no_color: bool, message: str, store: str) -> None:
|
def record_cli(
|
||||||
|
no_show: bool,
|
||||||
|
show_hashes: bool,
|
||||||
|
yes: bool,
|
||||||
|
no_color: bool,
|
||||||
|
message: str,
|
||||||
|
store: str,
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Initialize tracking or record changes to a tracked directory.
|
Initialize tracking or record changes to a tracked directory.
|
||||||
"""
|
"""
|
||||||
@ -87,4 +115,6 @@ def record_cli(show_hashes: bool, no_color: bool, message: str, store: str) -> N
|
|||||||
show_hashes=show_hashes,
|
show_hashes=show_hashes,
|
||||||
use_color=not no_color,
|
use_color=not no_color,
|
||||||
store_path=store,
|
store_path=store,
|
||||||
|
skip_confirm=yes,
|
||||||
|
show_diff=not no_show,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -154,7 +154,7 @@ class FSEntry:
|
|||||||
cls: Type[_FSEntryT],
|
cls: Type[_FSEntryT],
|
||||||
store: Optional["Store"] = None,
|
store: Optional["Store"] = None,
|
||||||
relpath: Optional[str] = None,
|
relpath: Optional[str] = None,
|
||||||
exclude: List[str] = ["nancy.db"],
|
exclude_prefixes: List[str] = ["nancy.db", "."],
|
||||||
parent: Optional[_FSEntryT] = None,
|
parent: Optional[_FSEntryT] = None,
|
||||||
direntry: Optional["os.DirEntry[str]"] = None,
|
direntry: Optional["os.DirEntry[str]"] = None,
|
||||||
) -> _FSEntryT:
|
) -> _FSEntryT:
|
||||||
@ -206,15 +206,23 @@ class FSEntry:
|
|||||||
for e in direntries
|
for e in direntries
|
||||||
)
|
)
|
||||||
|
|
||||||
children = [
|
children = []
|
||||||
cls.from_path(
|
for rp, e in zip(childrenrelpaths, direntries):
|
||||||
store=store,
|
skip = False
|
||||||
relpath=rp,
|
for p in exclude_prefixes:
|
||||||
direntry=e,
|
if os.path.basename(rp).startswith(p):
|
||||||
|
skip = True
|
||||||
|
break
|
||||||
|
if skip:
|
||||||
|
continue
|
||||||
|
children.append(
|
||||||
|
cls.from_path(
|
||||||
|
store=store,
|
||||||
|
relpath=rp,
|
||||||
|
direntry=e,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
for rp, e in zip(childrenrelpaths, direntries)
|
|
||||||
if rp not in exclude
|
|
||||||
]
|
|
||||||
for c in children: # now hash concatenated sorted hashes
|
for c in children: # now hash concatenated sorted hashes
|
||||||
# hash on perms+sha256 to enable recursively detecting perm
|
# hash on perms+sha256 to enable recursively detecting perm
|
||||||
# changes without modifying the hashes of individual files,
|
# changes without modifying the hashes of individual files,
|
||||||
|
|||||||
@ -129,7 +129,7 @@ class Program:
|
|||||||
name: str
|
name: str
|
||||||
message: str
|
message: str
|
||||||
|
|
||||||
start_time: Optional[datetime.datetime] = None
|
start_time: datetime.datetime = datetime.datetime.fromtimestamp(0)
|
||||||
evaluated: bool = False
|
evaluated: bool = False
|
||||||
|
|
||||||
uuid: str = ""
|
uuid: str = ""
|
||||||
@ -195,7 +195,7 @@ class Program:
|
|||||||
WHERE
|
WHERE
|
||||||
uuid = ?
|
uuid = ?
|
||||||
""",
|
""",
|
||||||
(self.start_time, end_time, self.uuid),
|
(self.start_time.timestamp(), end_time.timestamp(), self.uuid),
|
||||||
)
|
)
|
||||||
self.evaluated = True # prevent re-running
|
self.evaluated = True # prevent re-running
|
||||||
assert self.start_time is not None
|
assert self.start_time is not None
|
||||||
|
|||||||
@ -78,7 +78,6 @@ class Store:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def init(cls: Type[_StoreT], message: str, directory: fs.PathStr) -> _StoreT:
|
def init(cls: Type[_StoreT], message: str, directory: fs.PathStr) -> _StoreT:
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
if not os.path.isdir(directory):
|
if not os.path.isdir(directory):
|
||||||
raise FileNotFoundError(
|
raise FileNotFoundError(
|
||||||
f"Directory {directory} must exist before initializing a store there.",
|
f"Directory {directory} must exist before initializing a store there.",
|
||||||
@ -107,10 +106,6 @@ class Store:
|
|||||||
(new_store.uuid,),
|
(new_store.uuid,),
|
||||||
)
|
)
|
||||||
|
|
||||||
with new_store.new_program("INIT", message) as p:
|
|
||||||
# set the timing to the actual times it took to initialize the db
|
|
||||||
p.start_time = start_time
|
|
||||||
|
|
||||||
return new_store
|
return new_store
|
||||||
|
|
||||||
def filedir_root_key(self, cur: Optional[sqlite3.Cursor] = None) -> Optional[str]:
|
def filedir_root_key(self, cur: Optional[sqlite3.Cursor] = None) -> Optional[str]:
|
||||||
@ -188,26 +183,6 @@ class Store:
|
|||||||
|
|
||||||
return fs.FSDiff.compute(recorded, current)
|
return fs.FSDiff.compute(recorded, current)
|
||||||
|
|
||||||
def record(
|
|
||||||
self,
|
|
||||||
diff: fs.FSDiff,
|
|
||||||
message: str,
|
|
||||||
parent_id: Optional[str] = None,
|
|
||||||
cur: Optional[sqlite3.Cursor] = None,
|
|
||||||
) -> None:
|
|
||||||
if cur is None:
|
|
||||||
assert self.conn is not None
|
|
||||||
cur = self.conn.cursor()
|
|
||||||
|
|
||||||
with self.new_program("RECORD", message) as p:
|
|
||||||
with self.committing() as cur: # entire record operation is one transaction
|
|
||||||
# create a task for this operation
|
|
||||||
task = p.new_task(name="Store._record_recursive", cur=cur)
|
|
||||||
|
|
||||||
# descend the diff, tracking parent filedir IDs, creating them and
|
|
||||||
# recording new versions of each, when necessary
|
|
||||||
diff.persist(cur=cur, source_task=task)
|
|
||||||
|
|
||||||
|
|
||||||
def find_store(path: Union[str, "os.PathLike[str]"]) -> Optional[str]:
|
def find_store(path: Union[str, "os.PathLike[str]"]) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -22,6 +22,22 @@ def junk_dir() -> Iterator[Path]:
|
|||||||
|
|
||||||
def test_record(junk_dir: Path) -> None:
|
def test_record(junk_dir: Path) -> None:
|
||||||
runner = CliRunner()
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(
|
||||||
|
main,
|
||||||
|
[
|
||||||
|
"record",
|
||||||
|
"-s",
|
||||||
|
str(junk_dir),
|
||||||
|
"-m",
|
||||||
|
"This is just a test recording",
|
||||||
|
"--yes", # don't ask for confirmation
|
||||||
|
],
|
||||||
|
)
|
||||||
|
print(result.output)
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert "ERROR" not in result.output
|
||||||
|
|
||||||
|
# test again with confirmation
|
||||||
result = runner.invoke(
|
result = runner.invoke(
|
||||||
main,
|
main,
|
||||||
[
|
[
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user