merge of '7393275c6ccce67cadeb49d4afb3459e56edf8a9'
[vuplus_openembedded] / packages / stage-manager / files / stage-manager
1 #!/usr/bin/env python
2
3 # Copyright (C) 2006-2007 Richard Purdie
4 #
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
7 # Software Foundation;
8 #
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.
12
13 import optparse
14 import os, sys, stat
15
16 __version__ = "0.0.1"
17
18
19 def write_cache(cachefile, cachedata):
20     fd = open(cachefile, 'w')
21     for f in cachedata:
22         s = f + '|' + str(cachedata[f]['ts']) + '|' + str(cachedata[f]['size'])
23         fd.write(s + '\n')
24     fd.close()
25
26 def read_cache(cachefile):
27     cache = {}
28     f = open(cachefile, 'r')
29     lines = f.readlines()
30     f.close()
31     for l in lines:
32         data = l.split('|')
33         cache[data[0]] = {}
34         cache[data[0]]['ts'] = int(data[1])
35         cache[data[0]]['size'] = int(data[2])
36         cache[data[0]]['seen'] = False
37     return cache
38
39 def mkdirhier(dir):
40     """Create a directory like 'mkdir -p', but does not complain if
41     directory already exists like os.makedirs
42     """
43     try:
44         os.makedirs(dir)
45     except OSError, e:
46         if e.errno != 17: raise e
47
48 if __name__ == "__main__":
49     parser = optparse.OptionParser( version = "Metadata Stage Manager version %s" % ( __version__ ),
50     usage = """%prog [options]\n\nPerforms mamagement tasks on a metadata staging area.""" )
51
52     parser.add_option( "-p", "--parentdir", help = "the path to the metadata parent directory",
53                action = "store", dest = "parentdir", default = None)
54
55     parser.add_option( "-c", "--cachefile", help = "the cache file to use",
56                action = "store", dest = "cachefile", default = None)
57
58     parser.add_option( "-d", "--copydir", help = "copy changed files to this directory",
59                action = "store", dest = "copydir", default = None)
60
61     parser.add_option( "-u", "--update", help = "update the cache file",
62                action = "store_true", dest = "update", default = False)
63
64     (options, args) = parser.parse_args()
65
66     if options.parentdir is None:
67         print("Error, --parentdir option not supplied")
68         sys.exit(1)
69
70     if options.cachefile is None:
71         print("Error, --cachefile option not supplied")
72         sys.exit(1)
73
74     if not options.parentdir.endswith('/'):
75         options.parentdir = options.parentdir + '/'
76
77     cache = {}
78     if os.access(options.cachefile, os.F_OK):
79         cache = read_cache(options.cachefile)
80
81     found_difference = False
82
83     def updateCache(path, fstamp):
84         cache[path] = {}
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
89
90     def copyfile(path):
91         if options.copydir:
92             copypath = os.path.join(options.copydir, path.replace(options.parentdir, '', 1))
93             mkdirhier(os.path.split(copypath)[0])
94             os.system("cp -dp " + path + " " + copypath)
95
96     def copydir(path, fstamp):
97         if options.copydir:
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)
103             else:
104                 mkdirhier(copypath)
105                 os.utime(copypath, (fstamp[stat.ST_ATIME], fstamp[stat.ST_MTIME]))
106
107     for root, dirs, files in os.walk(options.parentdir):
108         for f in files:
109             path = os.path.join(root, f)
110             if not os.access(path, os.R_OK):
111                 continue
112             fstamp = os.lstat(path)
113             if path not in cache:
114                 print "new file %s" % path
115                 updateCache(path, fstamp)
116                 copyfile(path)
117             else:
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)
121                     copyfile(path)
122                 cache[path]['seen'] = True
123         for d in dirs:
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)
130             else:
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
136
137     todel = []
138     for path in cache:
139         if not cache[path]['seen']:
140             print "%s removed" % path
141             found_difference = True
142             todel.append(path)
143
144     if options.update:
145         print "Updating"
146         for path in todel:
147             del cache[path]
148         mkdirhier(os.path.split(options.cachefile)[0])
149         write_cache(options.cachefile, cache)
150
151     if found_difference:
152         sys.exit(5)
153     sys.exit(0)
154
155
156