started migrate --update

This is most of the way there, but not quite working.

The layout of migrate.tree/ needs to be changed to follow this approach.
git log will list all the files in tree order, so the new layout needs
to alternate old and new keys. Can that be done? git may not document
tree order, or may not preserve it here.

Alternatively, change to using git log --format=raw and extract
the tree header from that, then use
git diff --raw $tree:migrate.tree/old $tree:migrate.tree/new
That will be a little more expensive, but only when there are lots of
migrations.

Sponsored-by: Joshua Antonishen on Patreon
This commit is contained in:
Joey Hess 2023-12-07 15:50:52 -04:00
parent d06aee7ce0
commit f1ce15036f
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
9 changed files with 172 additions and 38 deletions

View file

@ -10,6 +10,7 @@ module Git.Log where
import Common
import Git
import Git.Command
import Git.Sha
import Data.Time
import Data.Time.Clock.POSIX
@ -28,14 +29,15 @@ data RefChange t = RefChange
-- run after processing the returned list.
getGitLog
:: Ref
-> Maybe Ref
-> [FilePath]
-> [CommandParam]
-> (FilePath -> Maybe t)
-> (Sha -> FilePath -> Maybe t)
-> Repo
-> IO ([RefChange t], IO Bool)
getGitLog ref fs os fileselector repo = do
getGitLog ref stopref fs os selector repo = do
(ls, cleanup) <- pipeNullSplit ps repo
return (parseGitRawLog fileselector (map decodeBL ls), cleanup)
return (parseGitRawLog selector (map decodeBL ls), cleanup)
where
ps =
[ Param "log"
@ -45,14 +47,16 @@ getGitLog ref fs os fileselector repo = do
, Param "--no-abbrev"
, Param "--no-renames"
] ++ os ++
[ Param (fromRef ref)
[ case stopref of
Just stopref' -> Param $
fromRef stopref' <> ".." <> fromRef ref
Nothing -> Param (fromRef ref)
, Param "--"
] ++ map Param fs
-- The commitinfo is the timestamp of the commit, followed by
-- the commit hash and then the commit's parents, separated by spaces.
-- The commitinfo is the commit hash followed by its timestamp.
commitinfoFormat :: String
commitinfoFormat = "%ct"
commitinfoFormat = "%H %ct"
-- Parses chunked git log --raw output generated by getGitLog,
-- which looks something like:
@ -69,21 +73,23 @@ commitinfoFormat = "%ct"
--
-- The commitinfo is not included before all changelines, so
-- keep track of the most recently seen commitinfo.
parseGitRawLog :: (FilePath -> Maybe t) -> [String] -> [RefChange t]
parseGitRawLog fileselector = parse epoch
parseGitRawLog :: (Ref -> FilePath -> Maybe t) -> [String] -> [RefChange t]
parseGitRawLog selector = parse (deleteSha, epoch)
where
epoch = toEnum 0 :: POSIXTime
parse oldts ([]:rest) = parse oldts rest
parse oldts (c1:c2:rest) = case mrc of
Just rc -> rc : parse ts rest
Nothing -> parse ts (c2:rest)
parse old ([]:rest) = parse old rest
parse (oldcommitsha, oldts) (c1:c2:rest) = case mrc of
Just rc -> rc : parse (commitsha, ts) rest
Nothing -> parse (commitsha, ts) (c2:rest)
where
(ts, cl) = case separate (== '\n') c1 of
(cl', []) -> (oldts, cl')
(tss, cl') -> (parseTimeStamp tss, cl')
(commitsha, ts, cl) = case separate (== '\n') c1 of
(cl', []) -> (oldcommitsha, oldts, cl')
(ci, cl') -> case words ci of
(css:tss:[]) -> (Ref (encodeBS css), parseTimeStamp tss, cl')
_ -> (oldcommitsha, oldts, cl')
mrc = do
(old, new) <- parseRawChangeLine cl
v <- fileselector c2
v <- selector commitsha c2
return $ RefChange
{ changetime = ts
, changed = v