make diff+patch work together, document
This commit is contained in:
parent
56cf7c69a9
commit
cb5257b285
86
Main.hs
86
Main.hs
|
|
@ -19,6 +19,8 @@ import Progs
|
||||||
import qualified Toks
|
import qualified Toks
|
||||||
import Toks (Tok)
|
import Toks (Tok)
|
||||||
|
|
||||||
|
import Debug.Trace
|
||||||
|
|
||||||
{-
|
{-
|
||||||
- merge algorithms
|
- merge algorithms
|
||||||
-}
|
-}
|
||||||
|
|
@ -42,6 +44,36 @@ data Merged
|
||||||
| Conflict [String] [String] [String]
|
| Conflict [String] [String] [String]
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
|
pmerge :: FilePath -> IO [Merged]
|
||||||
|
pmerge path = go . lines <$> readFile path
|
||||||
|
where
|
||||||
|
go [] = []
|
||||||
|
go xs@(x:_)
|
||||||
|
| Toks.tok x = goOk xs
|
||||||
|
| otherwise = goC0 xs
|
||||||
|
eat = span Toks.tok
|
||||||
|
goOk xs =
|
||||||
|
let (a, xs') = eat xs
|
||||||
|
in Ok a : go xs'
|
||||||
|
goC0 ("<<<<<<<":xs) =
|
||||||
|
let (m, xs') = eat xs
|
||||||
|
in goC1 m xs'
|
||||||
|
goC0 (x:_) = error $ "unexpected token: " ++ x
|
||||||
|
goC0 [] = error "unexpected end"
|
||||||
|
goC1 m ("|||||||":xs) =
|
||||||
|
let (o, xs') = eat xs
|
||||||
|
in goC2 m o xs'
|
||||||
|
goC1 _ (x:_) = error $ "unexpected token: " ++ x
|
||||||
|
goC1 _ [] = error "unexpected end"
|
||||||
|
goC2 m o ("=======":xs) =
|
||||||
|
let (y, xs') = eat xs
|
||||||
|
in goC3 m o y xs'
|
||||||
|
goC2 _ _ (x:_) = error $ "unexpected token: " ++ x
|
||||||
|
goC2 _ _ [] = error "unexpected end"
|
||||||
|
goC3 m o y (">>>>>>>":xs) = Conflict m o y : go xs
|
||||||
|
goC3 _ _ _ (x:_) = error $ "unexpected token: " ++ x
|
||||||
|
goC3 _ _ _ [] = error "unexpected end"
|
||||||
|
|
||||||
isKeepTok :: (Op, String) -> Bool
|
isKeepTok :: (Op, String) -> Bool
|
||||||
isKeepTok (Keep, _) = True
|
isKeepTok (Keep, _) = True
|
||||||
isKeepTok _ = False
|
isKeepTok _ = False
|
||||||
|
|
@ -182,19 +214,19 @@ expand n = go
|
||||||
go [] = []
|
go [] = []
|
||||||
go (x@(Conflict m1 o1 y1):xs) =
|
go (x@(Conflict m1 o1 y1):xs) =
|
||||||
case go xs of
|
case go xs of
|
||||||
(Conflict m2 o2 y2:xs') | n > 0 ->
|
(Conflict m2 o2 y2:xs')
|
||||||
Conflict (m1 ++ m2) (o1 ++ o2) (y1 ++ y2) : xs'
|
| n > 0 -> Conflict (m1 ++ m2) (o1 ++ o2) (y1 ++ y2) : xs'
|
||||||
(Ok a:Conflict m2 o2 y2:xs')
|
(Ok a:Conflict m2 o2 y2:xs')
|
||||||
| length a < n ->
|
| length a < n ->
|
||||||
Conflict (m1 ++ a ++ m2) (o1 ++ a ++ o2) (y1 ++ a ++ y2) : xs'
|
Conflict (m1 ++ a ++ m2) (o1 ++ a ++ o2) (y1 ++ a ++ y2) : xs'
|
||||||
xs' -> x : xs'
|
xs' -> x : xs'
|
||||||
go (x@(Replace o1 n1):xs) = case go xs of
|
go (x@(Replace o1 n1):xs) =
|
||||||
(Replace o2 n2:xs') | n > 0 ->
|
case go xs of
|
||||||
Replace (o1++o2) (n1++n2): xs'
|
(Replace o2 n2:xs')
|
||||||
(Ok a:Replace o2 n2:xs')
|
| n > 0 -> Replace (o1 ++ o2) (n1 ++ n2) : xs'
|
||||||
| length a < n ->
|
(Ok a:Replace o2 n2:xs')
|
||||||
Replace (o1++a++o2) (n1++a++n2): xs'
|
| length a < n -> Replace (o1 ++ a ++ o2) (n1 ++ a ++ n2) : xs'
|
||||||
xs' -> x : xs'
|
xs' -> x : xs'
|
||||||
go (x:xs) = x : go xs
|
go (x:xs) = x : go xs
|
||||||
|
|
||||||
resolve :: Config -> Merged -> Merged
|
resolve :: Config -> Merged -> Merged
|
||||||
|
|
@ -224,7 +256,7 @@ merge cfg@Config {..} ms ys =
|
||||||
. regroup
|
. regroup
|
||||||
$ align (chunks ms) (chunks ys)
|
$ align (chunks ms) (chunks ys)
|
||||||
|
|
||||||
diff Config{..} = expand cfgContext . chunks
|
diff Config {..} = expand cfgContext . chunks
|
||||||
|
|
||||||
{-
|
{-
|
||||||
- front-end
|
- front-end
|
||||||
|
|
@ -261,8 +293,8 @@ runCmd CmdDiff3 {..} cfg =
|
||||||
map (workdir </>) ["my", "old", "your", "mydiff", "yourdiff"]
|
map (workdir </>) ["my", "old", "your", "mydiff", "yourdiff"]
|
||||||
for_ [(d3my, fMy), (d3old, fOld), (d3your, fYour)] $ \(path, tmp) ->
|
for_ [(d3my, fMy), (d3old, fOld), (d3your, fYour)] $ \(path, tmp) ->
|
||||||
bracketFile path ReadMode $ \h -> hSplitToFile cfg h tmp
|
bracketFile path ReadMode $ \h -> hSplitToFile cfg h tmp
|
||||||
rundiff fOld fMy fdMy
|
runDiff fOld fMy fdMy
|
||||||
rundiff fOld fYour fdYour
|
runDiff fOld fYour fdYour
|
||||||
conflicted <-
|
conflicted <-
|
||||||
merge cfg <$> pdiff fdMy <*> pdiff fdYour >>= format cfg stdout
|
merge cfg <$> pdiff fdMy <*> pdiff fdYour >>= format cfg stdout
|
||||||
if conflicted
|
if conflicted
|
||||||
|
|
@ -280,8 +312,8 @@ runCmd CmdGitMerge {..} cfg = do
|
||||||
let [fMy, fOld, fYour, fdMy, fdYour] =
|
let [fMy, fOld, fYour, fdMy, fdYour] =
|
||||||
map (workdir </>) ["my", "old", "your", "mydiff", "yourdiff"]
|
map (workdir </>) ["my", "old", "your", "mydiff", "yourdiff"]
|
||||||
gitCheckoutMOY cfg u fMy fOld fYour
|
gitCheckoutMOY cfg u fMy fOld fYour
|
||||||
rundiff fOld fMy fdMy
|
runDiff fOld fMy fdMy
|
||||||
rundiff fOld fYour fdYour
|
runDiff fOld fYour fdYour
|
||||||
readFile u >>= writeFile (u ++ ".werge-backup")
|
readFile u >>= writeFile (u ++ ".werge-backup")
|
||||||
conflict <-
|
conflict <-
|
||||||
bracketFile u WriteMode $ \h ->
|
bracketFile u WriteMode $ \h ->
|
||||||
|
|
@ -293,14 +325,32 @@ runCmd CmdGitMerge {..} cfg = do
|
||||||
else exitSuccess
|
else exitSuccess
|
||||||
runCmd CmdDiff {..} cfg = do
|
runCmd CmdDiff {..} cfg = do
|
||||||
withSystemTempDirectory "werge-diff" $ \workdir -> do
|
withSystemTempDirectory "werge-diff" $ \workdir -> do
|
||||||
let [fOld, fNew, fDiff] = map (workdir </>) ["old", "new", "diff"]
|
let [fOld, fYour, fDiff] = map (workdir </>) ["old", "your", "diff"]
|
||||||
for_ [(diffOld, fOld), (diffNew, fNew)] $ \(path, tmp) ->
|
for_ [(diffOld, fOld), (diffYour, fYour)] $ \(path, tmp) ->
|
||||||
bracketFile path ReadMode $ \h -> hSplitToFile cfg h tmp
|
bracketFile path ReadMode $ \h -> hSplitToFile cfg h tmp
|
||||||
rundiff fOld fNew fDiff
|
conflicted <-
|
||||||
conflicted <- pdiff fDiff >>= format cfg stdout . diff cfg
|
case diffUnified of
|
||||||
|
Just u -> do
|
||||||
|
c <- runDiffRaw u fOld fYour fDiff
|
||||||
|
readFile fDiff >>= putStr . unlines . drop 2 . lines
|
||||||
|
pure c
|
||||||
|
Nothing -> do
|
||||||
|
runDiff fOld fYour fDiff
|
||||||
|
pdiff fDiff >>= format cfg stdout . diff cfg
|
||||||
if conflicted
|
if conflicted
|
||||||
then exitWith (ExitFailure 1)
|
then exitWith (ExitFailure 1)
|
||||||
else exitSuccess
|
else exitSuccess
|
||||||
|
runCmd CmdPatch {..} cfg = do
|
||||||
|
withSystemTempDirectory "werge-patch" $ \workdir -> do
|
||||||
|
let f = workdir </> "file"
|
||||||
|
bracketFile patchMy ReadMode $ \h -> hSplitToFile cfg h f
|
||||||
|
_ <- runPatch f stdin
|
||||||
|
conflicted <- pmerge f >>= format cfg stdout -- TODO try to resolve more?
|
||||||
|
if conflicted
|
||||||
|
then exitWith (ExitFailure 1)
|
||||||
|
else exitSuccess
|
||||||
|
runCmd CmdBreak cfg = hSplit cfg stdin stdout
|
||||||
|
runCmd CmdGlue _ = getContents >>= putStr . Toks.glue . Toks.fromFile
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = catch go bad
|
main = catch go bad
|
||||||
|
|
|
||||||
60
Opts.hs
60
Opts.hs
|
|
@ -224,9 +224,15 @@ data Command
|
||||||
, gmDoAdd :: Bool
|
, gmDoAdd :: Bool
|
||||||
}
|
}
|
||||||
| CmdDiff
|
| CmdDiff
|
||||||
{ diffOld :: FilePath
|
{ diffOld :: FilePath
|
||||||
, diffNew :: FilePath
|
, diffYour :: FilePath
|
||||||
}
|
, diffUnified :: Maybe Int
|
||||||
|
}
|
||||||
|
| CmdPatch
|
||||||
|
{ patchMy :: FilePath
|
||||||
|
}
|
||||||
|
| CmdBreak
|
||||||
|
| CmdGlue
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
cmdDiff3 :: Parser Command
|
cmdDiff3 :: Parser Command
|
||||||
|
|
@ -254,12 +260,11 @@ cmdGitMerge = do
|
||||||
]
|
]
|
||||||
gmDoAdd <-
|
gmDoAdd <-
|
||||||
asum
|
asum
|
||||||
[ flag'
|
[ flag' True
|
||||||
True
|
$ long "add"
|
||||||
(long "add"
|
<> short 'a'
|
||||||
<> short 'a'
|
<> help "Run `git add' for fully merged files"
|
||||||
<> help "Run `git add' for fully merged files")
|
, flag' False $ long "no-add" <> help "Prevent running `git add'"
|
||||||
, flag' False (long "no-add" <> help "Prevent running `git add'")
|
|
||||||
, pure False
|
, pure False
|
||||||
]
|
]
|
||||||
pure CmdGitMerge {..}
|
pure CmdGitMerge {..}
|
||||||
|
|
@ -267,9 +272,31 @@ cmdGitMerge = do
|
||||||
cmdDiff :: Parser Command
|
cmdDiff :: Parser Command
|
||||||
cmdDiff = do
|
cmdDiff = do
|
||||||
diffOld <- strArgument $ metavar "OLDFILE" <> help "Original file version"
|
diffOld <- strArgument $ metavar "OLDFILE" <> help "Original file version"
|
||||||
diffNew <- strArgument $ metavar "NEWFILE" <> help "File version with changes"
|
diffYour <-
|
||||||
|
strArgument $ metavar "YOURFILE" <> help "File version with changes"
|
||||||
|
diffUnified <-
|
||||||
|
asum
|
||||||
|
[ flag' (Just 20)
|
||||||
|
$ long "unified"
|
||||||
|
<> short 'u'
|
||||||
|
<> help
|
||||||
|
"Produce unified-diff-like output for `patch' with default context size (20)"
|
||||||
|
, fmap Just . option auto
|
||||||
|
$ long "unified-size"
|
||||||
|
<> short 'U'
|
||||||
|
<> help "Produce unified diff with this context size"
|
||||||
|
, flag Nothing Nothing
|
||||||
|
$ long "merge"
|
||||||
|
<> short 'm'
|
||||||
|
<> help "Highlight the differences as with `merge' (default)"
|
||||||
|
]
|
||||||
pure CmdDiff {..}
|
pure CmdDiff {..}
|
||||||
|
|
||||||
|
cmdPatch :: Parser Command
|
||||||
|
cmdPatch = do
|
||||||
|
patchMy <- strArgument $ metavar "MYFILE" <> help "File to be modified"
|
||||||
|
pure CmdPatch {..}
|
||||||
|
|
||||||
-- TODO have some option to output the (partially merged) my/old/your files so
|
-- TODO have some option to output the (partially merged) my/old/your files so
|
||||||
-- that folks can continue with external program or so (such as meld)
|
-- that folks can continue with external program or so (such as meld)
|
||||||
cmd :: Parser Command
|
cmd :: Parser Command
|
||||||
|
|
@ -284,12 +311,21 @@ cmd =
|
||||||
$ progDesc "Automerge unmerged files in git conflict"
|
$ progDesc "Automerge unmerged files in git conflict"
|
||||||
, command "diff"
|
, command "diff"
|
||||||
$ info cmdDiff
|
$ info cmdDiff
|
||||||
$ progDesc "Highlight differences between two files"
|
$ progDesc "Find differences between two files"
|
||||||
|
, command "patch"
|
||||||
|
$ info cmdPatch
|
||||||
|
$ progDesc "Apply a patch from `diff' to file"
|
||||||
|
, command "break"
|
||||||
|
$ info (pure CmdBreak)
|
||||||
|
$ progDesc "Break text to tokens"
|
||||||
|
, command "glue"
|
||||||
|
$ info (pure CmdGlue)
|
||||||
|
$ progDesc "Glue tokens back to text"
|
||||||
]
|
]
|
||||||
|
|
||||||
parseOpts :: IO (Config, Command)
|
parseOpts :: IO (Config, Command)
|
||||||
parseOpts =
|
parseOpts =
|
||||||
customExecParser (prefs helpShowGlobals)
|
customExecParser (prefs $ helpShowGlobals <> subparserInline)
|
||||||
$ info
|
$ info
|
||||||
(liftA2 (,) config cmd
|
(liftA2 (,) config cmd
|
||||||
<**> helper
|
<**> helper
|
||||||
|
|
|
||||||
44
Progs.hs
44
Progs.hs
|
|
@ -21,8 +21,11 @@ bracketFile path mode = bracket (openFile path mode) hClose
|
||||||
diffProg :: IO String
|
diffProg :: IO String
|
||||||
diffProg = fromMaybe "diff" <$> lookupEnv "WERGE_DIFF"
|
diffProg = fromMaybe "diff" <$> lookupEnv "WERGE_DIFF"
|
||||||
|
|
||||||
rundiff :: FilePath -> FilePath -> FilePath -> IO ()
|
patchProg :: IO String
|
||||||
rundiff f1 f2 out = do
|
patchProg = fromMaybe "patch" <$> lookupEnv "WERGE_PATCH"
|
||||||
|
|
||||||
|
runDiff :: FilePath -> FilePath -> FilePath -> IO ()
|
||||||
|
runDiff f1 f2 out = do
|
||||||
diff <- diffProg
|
diff <- diffProg
|
||||||
st <-
|
st <-
|
||||||
bracketFile out WriteMode $ \oh ->
|
bracketFile out WriteMode $ \oh ->
|
||||||
|
|
@ -41,6 +44,27 @@ rundiff f1 f2 out = do
|
||||||
unless (st `elem` [ExitSuccess, ExitFailure 1])
|
unless (st `elem` [ExitSuccess, ExitFailure 1])
|
||||||
$ error "diff failed for unknown reason (is GNU diffutils installed?)"
|
$ error "diff failed for unknown reason (is GNU diffutils installed?)"
|
||||||
|
|
||||||
|
runDiffRaw :: Int -> FilePath -> FilePath -> FilePath -> IO Bool
|
||||||
|
runDiffRaw u f1 f2 out = do
|
||||||
|
diff <- diffProg
|
||||||
|
st <-
|
||||||
|
bracketFile out WriteMode $ \oh ->
|
||||||
|
withCreateProcess
|
||||||
|
(proc diff ["--text", "--unified=" ++ show u, f1, f2])
|
||||||
|
{std_in = NoStream, std_out = UseHandle oh} $ \_ _ _ -> waitForProcess
|
||||||
|
unless (st `elem` [ExitSuccess, ExitFailure 1]) $ error "diff failed"
|
||||||
|
pure (st /= ExitSuccess) -- report if diff thinks that the files differed
|
||||||
|
|
||||||
|
runPatch :: FilePath -> Handle -> IO Bool
|
||||||
|
runPatch f hi = do
|
||||||
|
patch <- patchProg
|
||||||
|
st <-
|
||||||
|
withCreateProcess
|
||||||
|
(proc patch ["--silent", "--batch", "--merge=diff3", f])
|
||||||
|
{std_in = UseHandle hi} $ \_ _ _ -> waitForProcess
|
||||||
|
unless (st `elem` [ExitSuccess, ExitFailure 1]) $ error "patch failed"
|
||||||
|
pure (st /= ExitSuccess) -- report if patch thinks that stuff has failed
|
||||||
|
|
||||||
{-
|
{-
|
||||||
- interface to git
|
- interface to git
|
||||||
-}
|
-}
|
||||||
|
|
@ -115,17 +139,19 @@ gitAdd path = do
|
||||||
- TODO this might probably enforce joinSpaces?
|
- TODO this might probably enforce joinSpaces?
|
||||||
- or have joinSpaces as configurable? (probably best, default true)
|
- or have joinSpaces as configurable? (probably best, default true)
|
||||||
-}
|
-}
|
||||||
hSplitToFile :: Config -> Handle -> FilePath -> IO ()
|
hSplit :: Config -> Handle -> Handle -> IO ()
|
||||||
hSplitToFile cfg h path =
|
hSplit cfg hi ho =
|
||||||
case cfgTokenizer cfg of
|
case cfgTokenizer cfg of
|
||||||
TokenizeCharCategory -> internal Toks.splitCategory
|
TokenizeCharCategory -> internal Toks.splitCategory
|
||||||
TokenizeCharCategorySimple -> internal Toks.splitSimple
|
TokenizeCharCategorySimple -> internal Toks.splitSimple
|
||||||
TokenizeFilter fltr -> do
|
TokenizeFilter fltr -> do
|
||||||
st <-
|
st <-
|
||||||
bracketFile path WriteMode $ \ho ->
|
withCreateProcess
|
||||||
withCreateProcess
|
(shell fltr) {std_in = UseHandle ho, std_out = UseHandle ho} $ \_ _ _ ->
|
||||||
(shell fltr) {std_in = UseHandle h, std_out = UseHandle ho} $ \_ _ _ ->
|
waitForProcess
|
||||||
waitForProcess
|
|
||||||
unless (st == ExitSuccess) $ error "tokenize filter failed"
|
unless (st == ExitSuccess) $ error "tokenize filter failed"
|
||||||
where
|
where
|
||||||
internal s = hGetContents h >>= writeFile path . Toks.toFile . s
|
internal s = hGetContents hi >>= hPutStr ho . Toks.toFile . s
|
||||||
|
|
||||||
|
hSplitToFile :: Config -> Handle -> FilePath -> IO ()
|
||||||
|
hSplitToFile cfg hi path = bracketFile path WriteMode $ hSplit cfg hi
|
||||||
|
|
|
||||||
74
README.md
74
README.md
|
|
@ -144,16 +144,16 @@ automatically to `filename.werge-backup`.
|
||||||
```
|
```
|
||||||
werge -- blanks-friendly mergetool for tiny interdwindled changes
|
werge -- blanks-friendly mergetool for tiny interdwindled changes
|
||||||
|
|
||||||
Usage: werge [(-F|--tok-filter FILTER) | (-i|--simple-tokens) |
|
Usage: werge [(-F|--tok-filter FILTER) | (-i|--simple-tokens) |
|
||||||
(-I|--full-tokens)] [--no-zeal | (-z|--zeal)]
|
(-I|--full-tokens)] [--no-zeal | (-z|--zeal)]
|
||||||
[-S|--space (keep|my|old|your)]
|
[-S|--space (keep|my|old|your)]
|
||||||
[-s | --resolve-space (normal|keep|my|old|your)]
|
[-s | --resolve-space (normal|keep|my|old|your)]
|
||||||
[--conflict-space-overlaps] [--conflict-space-separate]
|
[--conflict-space-overlaps] [--conflict-space-separate]
|
||||||
[--conflict-space-all] [-C|--expand-context N]
|
[--conflict-space-all] [-C|--expand-context N]
|
||||||
[--resolve (keep|my|old|your)] [--conflict-overlaps]
|
[--resolve (keep|my|old|your)] [--conflict-overlaps]
|
||||||
[--conflict-separate] [--conflict-all] [-G|--color]
|
[--conflict-separate] [--conflict-all] [-G|--color]
|
||||||
[--label-start "<<<<<"] [--label-mo "|||||"] [--label-oy "====="]
|
[--label-start "<<<<<"] [--label-mo "|||||"] [--label-diff "|||||"]
|
||||||
[--label-end ">>>>>"] COMMAND
|
[--label-oy "====="] [--label-end ">>>>>"] COMMAND
|
||||||
|
|
||||||
Available options:
|
Available options:
|
||||||
-F,--tok-filter FILTER External program to separate the text to tokens
|
-F,--tok-filter FILTER External program to separate the text to tokens
|
||||||
|
|
@ -183,9 +183,10 @@ Available options:
|
||||||
Never resolve separate (non-overlapping) changes in
|
Never resolve separate (non-overlapping) changes in
|
||||||
space-only tokens
|
space-only tokens
|
||||||
--conflict-space-all Never resolve any changes in space-only tokens
|
--conflict-space-all Never resolve any changes in space-only tokens
|
||||||
-C,--expand-context N Consider changes that are at most N tokens apart to
|
-C,--expand-context N Consider changes that are at less than N tokens apart
|
||||||
be a single change. Zero may cause bad resolutions of
|
to be a single change; 0 turns off conflict
|
||||||
near conflicting edits (default: 1)
|
expansion, 1 may cause bad resolutions of near
|
||||||
|
conflicting edits (default: 2)
|
||||||
--resolve (keep|my|old|your)
|
--resolve (keep|my|old|your)
|
||||||
Resolve general conflicts in favor of a given
|
Resolve general conflicts in favor of a given
|
||||||
version, or keep the conflicts (default: keep)
|
version, or keep the conflicts (default: keep)
|
||||||
|
|
@ -198,6 +199,7 @@ Available options:
|
||||||
`less -R')
|
`less -R')
|
||||||
--label-start "<<<<<" Label for beginning of the conflict
|
--label-start "<<<<<" Label for beginning of the conflict
|
||||||
--label-mo "|||||" Separator of local edits and original
|
--label-mo "|||||" Separator of local edits and original
|
||||||
|
--label-diff "|||||" Separator for old and new version
|
||||||
--label-oy "=====" Separator of original and other people's edits
|
--label-oy "=====" Separator of original and other people's edits
|
||||||
--label-end ">>>>>" Label for end of the conflict
|
--label-end ">>>>>" Label for end of the conflict
|
||||||
-h,--help Show this help text
|
-h,--help Show this help text
|
||||||
|
|
@ -206,6 +208,10 @@ Available options:
|
||||||
Available commands:
|
Available commands:
|
||||||
merge diff3-style merge of two changesets
|
merge diff3-style merge of two changesets
|
||||||
git Automerge unmerged files in git conflict
|
git Automerge unmerged files in git conflict
|
||||||
|
diff Find differences between two files
|
||||||
|
patch Apply a patch from `diff' to file
|
||||||
|
break Break text to tokens
|
||||||
|
glue Glue tokens back to text
|
||||||
|
|
||||||
werge is a free software, use it accordingly.
|
werge is a free software, use it accordingly.
|
||||||
```
|
```
|
||||||
|
|
@ -237,3 +243,45 @@ Available options:
|
||||||
--no-add Prevent running `git add'
|
--no-add Prevent running `git add'
|
||||||
-h,--help Show this help text
|
-h,--help Show this help text
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Finding differences
|
||||||
|
```
|
||||||
|
Usage: werge diff OLDFILE YOURFILE
|
||||||
|
[(-u|--unified) | (-U|--unified-size ARG) | (-m|--merge)]
|
||||||
|
|
||||||
|
Find differences between two files
|
||||||
|
|
||||||
|
Available options:
|
||||||
|
OLDFILE Original file version
|
||||||
|
YOURFILE File version with changes
|
||||||
|
-u,--unified Produce unified-diff-like output for `patch' with
|
||||||
|
default context size (20)
|
||||||
|
-U,--unified-size ARG Produce unified diff with this context size
|
||||||
|
-m,--merge Highlight the differences as with `merge' (default)
|
||||||
|
-h,--help Show this help text
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Patching files in place
|
||||||
|
```
|
||||||
|
Usage: werge patch MYFILE
|
||||||
|
|
||||||
|
Apply a patch from `diff' to file
|
||||||
|
|
||||||
|
Available options:
|
||||||
|
MYFILE File to be modified
|
||||||
|
-h,--help Show this help text
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Converting between files and tokens
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage: werge break
|
||||||
|
|
||||||
|
Break text to tokens
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage: werge glue
|
||||||
|
|
||||||
|
Glue tokens back to text
|
||||||
|
```
|
||||||
|
|
|
||||||
8
Toks.hs
8
Toks.hs
|
|
@ -18,15 +18,19 @@ unescape ('\\':'n':xs) = '\n' : unescape xs
|
||||||
unescape ('\\':_) = error "bad escape on input"
|
unescape ('\\':_) = error "bad escape on input"
|
||||||
unescape (x:xs) = x : unescape xs
|
unescape (x:xs) = x : unescape xs
|
||||||
|
|
||||||
|
tok ('.':_) = True
|
||||||
|
tok ('/':_) = True
|
||||||
|
tok _ = False
|
||||||
|
|
||||||
markSpace :: String -> Tok
|
markSpace :: String -> Tok
|
||||||
markSpace [] = error "empty token"
|
markSpace [] = error "empty token"
|
||||||
markSpace s@(c:_)
|
markSpace s@(c:_)
|
||||||
| isSpace c = '.' : s
|
| isSpace c = '.' : s
|
||||||
| otherwise = '|' : s
|
| otherwise = '/' : s
|
||||||
|
|
||||||
unmarkSpace :: Tok -> String
|
unmarkSpace :: Tok -> String
|
||||||
unmarkSpace ('.':s) = s
|
unmarkSpace ('.':s) = s
|
||||||
unmarkSpace ('|':s) = s
|
unmarkSpace ('/':s) = s
|
||||||
unmarkSpace _ = error "bad space marking on input"
|
unmarkSpace _ = error "bad space marking on input"
|
||||||
|
|
||||||
space :: Tok -> Bool
|
space :: Tok -> Bool
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue