summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2011-03-14 23:00:23 -0400
committerGravatar Joey Hess <joey@kitenet.net>2011-03-14 23:00:23 -0400
commitbc5c54c987f548505a3877e8a0e460abe0b2a081 (patch)
tree4074e799eef10edb2060abf9d1ba2863c47b256c
parent96e074bb0333b6952fb9fbce2f0a810ebafd3d2c (diff)
symlink touching fun
When adding files to the annex, the symlinks pointing at the annexed content are made to have the same mtime as the original file. While git does not preserve that information, this allows a tool like metastore to be used with annexed files.
-rw-r--r--.gitignore1
-rw-r--r--Command/Add.hs7
-rw-r--r--Command/Find.hs1
-rw-r--r--Command/PreCommit.hs1
-rw-r--r--Makefile7
-rw-r--r--Touch.hsc70
-rw-r--r--debian/changelog4
-rw-r--r--doc/bugs/softlink_atime.mdwn14
8 files changed, 101 insertions, 4 deletions
diff --git a/.gitignore b/.gitignore
index 764a1af9d..69d2c8070 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,4 @@ doc/.ikiwiki
html
*.tix
.hpc
+Touch.hs
diff --git a/Command/Add.hs b/Command/Add.hs
index 26e7fa258..09fff7cff 100644
--- a/Command/Add.hs
+++ b/Command/Add.hs
@@ -18,6 +18,7 @@ import Types
import Content
import Messages
import Utility
+import Touch
command :: [Command]
command = [Command "add" paramPath seek "add files to annex"]
@@ -53,5 +54,11 @@ cleanup file key = do
link <- calcGitLink file key
liftIO $ createSymbolicLink link file
+
+ -- touch the symlink to have the same mtime as the file it points to
+ s <- liftIO $ getFileStatus file
+ let mtime = modificationTime s
+ _ <- liftIO $ touch file (TimeSpec mtime 0) False
+
Annex.queue "add" [Param "--"] file
return True
diff --git a/Command/Find.hs b/Command/Find.hs
index 1ca6ff1e7..3ed15c153 100644
--- a/Command/Find.hs
+++ b/Command/Find.hs
@@ -12,7 +12,6 @@ import Control.Monad.State (liftIO)
import Command
import Content
-import Messages
command :: [Command]
command = [Command "find" (paramOptional $ paramRepeating paramPath) seek
diff --git a/Command/PreCommit.hs b/Command/PreCommit.hs
index 6f9adb79a..1465ebc61 100644
--- a/Command/PreCommit.hs
+++ b/Command/PreCommit.hs
@@ -14,7 +14,6 @@ import qualified Annex
import qualified GitRepo as Git
import qualified Command.Add
import qualified Command.Fix
-import Messages
import Utility
command :: [Command]
diff --git a/Makefile b/Makefile
index c888fc215..c381ae986 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,10 @@ SysConfig.hs: configure.hs TestConfig.hs
$(GHCMAKE) configure
./configure
-$(bins): SysConfig.hs
+Touch.hs: Touch.hsc
+ hsc2hs $<
+
+$(bins): SysConfig.hs Touch.hs
$(GHCMAKE) $@
git-annex.1: doc/git-annex.mdwn
@@ -57,7 +60,7 @@ docs: $(mans)
--exclude='news/.*'
clean:
- rm -rf build $(bins) $(mans) test configure SysConfig.hs *.tix .hpc
+ rm -rf build $(bins) $(mans) test configure Touch.hs SysConfig.hs *.tix .hpc
rm -rf doc/.ikiwiki html
find . \( -name \*.o -or -name \*.hi \) -exec rm {} \;
diff --git a/Touch.hsc b/Touch.hsc
new file mode 100644
index 000000000..ad36761c4
--- /dev/null
+++ b/Touch.hsc
@@ -0,0 +1,70 @@
+{- More control over touching a file.
+ -
+ - Copyright 2011 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+module Touch (
+ TimeSpec(..),
+ now,
+ omit,
+ touchBoth,
+ touch
+) where
+
+import Foreign
+import Foreign.C
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
+
+data TimeSpec = TimeSpec CTime CLong
+
+instance Storable TimeSpec where
+ alignment _ = #{alignment struct timespec}
+ sizeOf _ = #{size struct timespec}
+ peek ptr = do
+ sec <- #{peek struct timespec, tv_sec} ptr
+ nsec <- #{peek struct timespec, tv_nsec} ptr
+ return $ TimeSpec sec nsec
+ poke ptr (TimeSpec sec nsec) = do
+ #{poke struct timespec, tv_sec} ptr sec
+ #{poke struct timespec, tv_nsec} ptr nsec
+
+{- special timespecs -}
+omit :: TimeSpec
+omit = TimeSpec 0 #const UTIME_OMIT
+now :: TimeSpec
+now = TimeSpec 0 #const UTIME_NOW
+
+{- While its interface is beastly, utimensat is in recent
+ POSIX standards, unlike futimes. -}
+foreign import ccall "utimensat"
+ c_utimensat :: CInt -> CString -> Ptr TimeSpec -> CInt -> IO CInt
+
+{- Changes the access and/or modification times of a file.
+ Can follow symlinks, or not. -}
+touchBoth :: FilePath -> TimeSpec -> TimeSpec -> Bool -> IO Bool
+touchBoth file atime mtime follow =
+ allocaArray 2 $ \ptr ->
+ withCString file $ \f -> do
+ pokeArray ptr [atime, mtime]
+ r <- c_utimensat at_fdcwd f ptr flags
+ putStrLn $ "ret " ++ (show r)
+ return (r == 0)
+ where
+ at_fdcwd = #const AT_FDCWD
+ at_symlink_nofollow = #const AT_SYMLINK_NOFOLLOW
+
+ flags = if follow
+ then 0
+ else at_symlink_nofollow
+
+touch :: FilePath -> TimeSpec -> Bool -> IO Bool
+touch file mtime follow = touchBoth file omit mtime follow
diff --git a/debian/changelog b/debian/changelog
index 6e70ac67e..e7017a26d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,6 +1,10 @@
git-annex (0.24) UNRELEASED; urgency=low
* Add Suggests on graphviz. Closes: #618039
+ * When adding files to the annex, the symlinks pointing at the annexed
+ content are made to have the same mtime as the original file.
+ While git does not preserve that information, this allows a tool
+ like metastore to be used with annexed files.
-- Joey Hess <joeyh@debian.org> Sun, 13 Mar 2011 14:25:17 -0400
diff --git a/doc/bugs/softlink_atime.mdwn b/doc/bugs/softlink_atime.mdwn
index 49e26013f..ebb040dd1 100644
--- a/doc/bugs/softlink_atime.mdwn
+++ b/doc/bugs/softlink_atime.mdwn
@@ -21,3 +21,17 @@ Optionally, editing the meta-data should change the times in all annexes.
>>> unlikely to do it better.
>>>> OK, thanks for the clarification. Would it be acceptable for you to put the timestamps into the metastore with vanilla git? If such an option existed, everyone would be able to benefit and not just me. -- RichiH
+
+>>>>> I've now committed to git changes to make git-annex add make
+>>>>> symlinks that reflect the original file's mtime. (It's not possible
+>>>>> to set the ctime of a symlink; nor would you want to as messing with
+>>>>> ctimes can break backup software ... and atime doesn't much matter.)
+>>>>>
+>>>>> So all you have to do is make the pre-commit hook call
+>>>>> [metastore](http://david.hardeman.nu/software.php). The hook
+>>>>> would look like this: ---[[Joey]] [[!tag done]]
+
+ #!/bin/sh
+ git annex pre-commit .
+ metastore --save
+ git add .metadata