3 # Copyright (C) 2006-2007 Richard Purdie
5 # This program is free software; you can redistribute it and/or modify it under
6 # the terms of the GNU General Public License version 2 as published by the Free
9 # This program is distributed in the hope that it will be useful, but WITHOUT
10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19 def write_cache(cachefile
, cachedata
):
20 fd
= open(cachefile
, 'w')
22 s
= f
+ '|' + str(cachedata
[f
]['ts']) + '|' + str(cachedata
[f
]['size'])
26 def read_cache(cachefile
):
28 f
= open(cachefile
, 'r')
34 cache
[data
[0]]['ts'] = int(data
[1])
35 cache
[data
[0]]['size'] = int(data
[2])
36 cache
[data
[0]]['seen'] = False
40 """Create a directory like 'mkdir -p', but does not complain if
41 directory already exists like os.makedirs
46 if e
.errno
!= 17: raise e
48 if __name__
== "__main__":
49 parser
= optparse
.OptionParser( version
= "Metadata Stage Manager version %s" % ( __version__
),
50 usage
= """%prog [options]\n\nPerforms management tasks on a metadata staging area.""" )
52 parser
.add_option( "-p", "--parentdir", help = "the path to the metadata parent directory",
53 action
= "store", dest
= "parentdir", default
= None)
55 parser
.add_option( "-c", "--cachefile", help = "the cache file to use",
56 action
= "store", dest
= "cachefile", default
= None)
58 parser
.add_option( "-d", "--copydir", help = "copy changed files to this directory",
59 action
= "store", dest
= "copydir", default
= None)
61 parser
.add_option( "-u", "--update", help = "update the cache file",
62 action
= "store_true", dest
= "update", default
= False)
64 (options
, args
) = parser
.parse_args()
66 if options
.parentdir
is None:
67 print("Error, --parentdir option not supplied")
70 if options
.cachefile
is None:
71 print("Error, --cachefile option not supplied")
74 if not options
.parentdir
.endswith('/'):
75 options
.parentdir
= options
.parentdir
+ '/'
78 if os
.access(options
.cachefile
, os
.F_OK
):
79 cache
= read_cache(options
.cachefile
)
81 found_difference
= False
83 def updateCache(path
, fstamp
):
85 cache
[path
]['ts'] = fstamp
[stat
.ST_MTIME
]
86 cache
[path
]['size'] = fstamp
[stat
.ST_SIZE
]
87 cache
[path
]['seen'] = True
88 found_difference
= True
92 copypath
= os
.path
.join(options
.copydir
, path
.replace(options
.parentdir
, '', 1))
93 mkdirhier(os
.path
.split(copypath
)[0])
94 os
.system("cp -Pp " + path
+ " " + copypath
)
96 def copydir(path
, fstamp
):
98 copypath
= os
.path
.join(options
.copydir
, path
.replace(options
.parentdir
, '', 1))
99 if os
.path
.exists(copypath
):
100 os
.system("rm -rf " + copypath
)
101 if os
.path
.islink(path
):
102 os
.symlink(os
.readlink(path
), copypath
)
105 os
.utime(copypath
, (fstamp
[stat
.ST_ATIME
], fstamp
[stat
.ST_MTIME
]))
107 for root
, dirs
, files
in os
.walk(options
.parentdir
):
109 path
= os
.path
.join(root
, f
)
110 if not os
.access(path
, os
.R_OK
):
112 fstamp
= os
.lstat(path
)
113 if path
not in cache
:
114 print "new file %s" % path
115 updateCache(path
, fstamp
)
118 if cache
[path
]['ts'] != fstamp
[stat
.ST_MTIME
] or cache
[path
]['size'] != fstamp
[stat
.ST_SIZE
]:
119 print "file %s changed" % path
120 updateCache(path
, fstamp
)
122 cache
[path
]['seen'] = True
124 path
= os
.path
.join(root
, d
)
125 fstamp
= os
.lstat(path
)
126 if path
not in cache
:
127 print "new dir %s" % path
128 updateCache(path
, fstamp
)
129 copydir(path
, fstamp
)
131 if cache
[path
]['ts'] != fstamp
[stat
.ST_MTIME
]:
132 print "dir %s changed" % path
133 updateCache(path
, fstamp
)
134 copydir(path
, fstamp
)
135 cache
[path
]['seen'] = True
139 if not cache
[path
]['seen']:
140 print "%s removed" % path
141 found_difference
= True
148 mkdirhier(os
.path
.split(options
.cachefile
)[0])
149 write_cache(options
.cachefile
, cache
)