1 # Copyright (C) 2006, Thomas Leonard
2 # See the README file for details, or visit http://0install.net.
5 from zeroinstall
.zerostore
.manifest
import generate_manifest
6 from zeroinstall
import zerostore
, SafeException
14 stores
= zerostore
.Stores()
16 class UsageError(SafeException
): pass
18 def do_manifest(args
):
19 """manifest DIRECTORY"""
20 if len(args
) != 1: raise UsageError("Wrong number of arguments")
23 for line
in generate_manifest(args
[0]):
25 digest
.update(line
+ '\n')
26 print "sha1=" + digest
.hexdigest()
31 if len(args
) != 1: raise UsageError("Wrong number of arguments")
33 print stores
.lookup(args
[0])
35 except zerostore
.BadDigest
, ex
:
36 print >>sys
.stderr
, ex
37 except zerostore
.NotStored
, ex
:
38 print >>sys
.stderr
, ex
42 """add DIGEST (DIRECTORY | (ARCHIVE [EXTRACT])"""
43 if len(args
) < 2: raise UsageError("Missing arguments")
45 if os
.path
.isdir(args
[1]):
46 if len(args
) > 2: raise UsageError("Too many arguments")
47 stores
.add_dir_to_cache(digest
, args
[1])
48 elif os
.path
.isfile(args
[1]):
49 if len(args
) > 3: raise UsageError("Too many arguments")
54 stores
.add_archive_to_cache(digest
, file(args
[1]), args
[1], extract
)
56 raise UsageError("No such file or directory '%s'" % args
[1])
59 """verify (DIGEST | DIRECTORY)"""
60 if len(args
) != 1: raise UsageError("Missing DIGEST or DIRECTORY")
61 root
= get_stored(args
[0])
63 print "Verifying", root
65 required_digest
= os
.path
.basename(args
[0])
66 if not required_digest
.startswith('sha1='):
67 raise zerostore
.BadDigest("Directory name '%s' does not start with 'sha1='" %
72 for line
in generate_manifest(root
):
76 actual_digest
= 'sha1=' + digest
.hexdigest()
78 manifest_file
= os
.path
.join(root
, '.manifest')
79 if os
.path
.isfile(manifest_file
):
81 digest
.update(file(manifest_file
).read())
82 manifest_digest
= 'sha1=' + digest
.hexdigest()
84 manifest_digest
= None
87 if required_digest
== actual_digest
== manifest_digest
:
91 print "Cached item does NOT verify:\n" + \
92 " Expected digest: " + required_digest
+ "\n" + \
93 " Actual digest: " + actual_digest
+ "\n" + \
94 ".manifest digest: " + (manifest_digest
or 'No .manifest file')
97 if manifest_digest
is None:
98 print "No .manifest, so no further details available."
99 elif manifest_digest
== actual_digest
:
100 print "The .manifest file matches the actual contents."
101 print "Very strange!"
102 elif manifest_digest
== required_digest
:
103 print "The .manifest file matches directory name. The "
104 print "contents of the directory have changed:"
105 show_changes(lines
, file(manifest_file
).readlines())
106 elif required_digest
== actual_digest
:
107 print "The directory contents are correct, but the .manifest file is "
110 print "The .manifest file matches neither of the other digests."
114 def show_changes(actual
, saved
):
116 for line
in difflib
.unified_diff(saved
, actual
, 'Recorded', 'Actual'):
121 if args
: raise UsageError("List takes no arguments")
122 print "User store (writable) : " + stores
.stores
[0].dir
123 for s
in stores
.stores
[1:]:
124 print "System store : " + s
.dir
125 if len(stores
.stores
) < 2:
126 print "No system stores."
128 def get_stored(dir_or_digest
):
129 if os
.path
.isdir(dir_or_digest
):
133 return stores
.lookup(dir_or_digest
)
134 except zerostore
.NotStored
, ex
:
135 print >>sys
.stderr
, ex
138 commands
= [do_add
, do_find
, do_list
, do_manifest
, do_verify
]