4 from twisted.python import usage
5 from allmydata.util.stringutils import unicode_to_url
6 from allmydata.util.assertutil import precondition
9 # unit tests can override these to point at StringIO instances
15 ["quiet", "q", "Operate silently."],
16 ["version", "V", "Display version numbers and exit."],
17 ["version-and-path", None, "Display version numbers and paths to their locations and exit."],
20 def opt_version(self):
22 print allmydata.get_package_versions_string()
25 def opt_version_and_path(self):
27 print allmydata.get_package_versions_string(show_paths=True)
33 ["multiple", "m", "allow multiple basedirs to be specified at once"],
36 def postOptions(self):
38 raise usage.UsageError("<basedir> parameter is required")
41 self['basedirs'] = [os.path.abspath(os.path.expanduser(b)) for b in self.basedirs]
43 def parseArgs(self, *args):
44 from allmydata.util.assertutil import precondition
47 precondition(isinstance(self['basedir'], (str, unicode)), self['basedir'])
48 self.basedirs.append(self['basedir'])
50 precondition(not [x for x in args if not isinstance(x, (str, unicode))], args)
51 self.basedirs.extend(args)
53 if len(args) == 0 and not self.basedirs:
54 if sys.platform == 'win32':
55 from allmydata.windows import registry
56 rbdp = registry.get_base_dir_path()
58 precondition(isinstance(registry.get_base_dir_path(), (str, unicode)), registry.get_base_dir_path())
59 self.basedirs.append(rbdp)
61 precondition(isinstance(os.path.expanduser("~/.tahoe"), (str, unicode)), os.path.expanduser("~/.tahoe"))
62 self.basedirs.append(os.path.expanduser("~/.tahoe"))
64 precondition(isinstance(args[0], (str, unicode)), args[0])
65 self.basedirs.append(args[0])
67 raise usage.UsageError("I wasn't expecting so many arguments")
69 class NoDefaultBasedirMixin(BasedirMixin):
70 def parseArgs(self, *args):
71 from allmydata.util.assertutil import precondition
72 # create-client won't default to --basedir=~/.tahoe
75 precondition(isinstance(self['basedir'], (str, unicode)), self['basedir'])
76 self.basedirs.append(self['basedir'])
78 precondition(not [x for x in args if not isinstance(x, (str, unicode))], args)
79 self.basedirs.extend(args)
82 precondition(isinstance(args[0], (str, unicode)), args[0])
83 self.basedirs.append(args[0])
85 raise usage.UsageError("I wasn't expecting so many arguments")
87 raise usage.UsageError("--basedir must be provided")
89 DEFAULT_ALIAS = "tahoe"
92 def get_aliases(nodedir):
93 from allmydata import uri
95 aliasfile = os.path.join(nodedir, "private", "aliases")
96 rootfile = os.path.join(nodedir, "private", "root_dir.cap")
98 f = open(rootfile, "r")
99 rootcap = f.read().strip()
101 aliases["tahoe"] = uri.from_string_dirnode(rootcap).to_string()
102 except EnvironmentError:
105 f = codecs.open(aliasfile, "r", "utf-8")
106 for line in f.readlines():
108 if line.startswith("#") or not line:
110 name, cap = line.split(":", 1)
111 # normalize it: remove http: prefix, urldecode
112 cap = cap.strip().encode('utf-8')
113 aliases[name] = uri.from_string_dirnode(cap).to_string()
114 except EnvironmentError:
118 class DefaultAliasMarker:
121 pretend_platform_uses_lettercolon = False # for tests
122 def platform_uses_lettercolon_drivename():
123 if ("win32" in sys.platform.lower()
124 or "cygwin" in sys.platform.lower()
125 or pretend_platform_uses_lettercolon):
129 class UnknownAliasError(Exception):
132 def get_alias(aliases, path, default):
133 from allmydata import uri
134 # transform "work:path/filename" into (aliases["work"], "path/filename").
135 # If default=None, then an empty alias is indicated by returning
136 # DefaultAliasMarker. We special-case strings with a recognized cap URI
137 # prefix, to make it easy to access specific files/directories by their
139 # If the transformed alias is either not found in aliases, or is blank
140 # and default is not found in aliases, an UnknownAliasError is
143 if uri.has_uri_prefix(path.encode('utf-8')):
144 # We used to require "URI:blah:./foo" in order to get a subpath,
145 # stripping out the ":./" sequence. We still allow that for compatibility,
146 # but now also allow just "URI:blah/foo".
147 sep = path.find(":./")
149 return path[:sep], path[sep+3:]
152 return path[:sep], path[sep+1:]
154 colon = path.find(":")
158 return DefaultAliasMarker, path
159 if default not in aliases:
160 raise UnknownAliasError("No alias specified, and the default "
161 "'tahoe' alias doesn't exist. To create "
162 "it, use 'tahoe create-alias tahoe'.")
163 return aliases[default], path
164 if colon == 1 and default == None and platform_uses_lettercolon_drivename():
165 # treat C:\why\must\windows\be\so\weird as a local path, not a tahoe
166 # file in the "C:" alias
167 return DefaultAliasMarker, path
170 # no alias, but there's a colon in a dirname/filename, like
173 return DefaultAliasMarker, path
174 if default not in aliases:
175 raise UnknownAliasError("No alias specified, and the default "
176 "'tahoe' alias doesn't exist. To create "
177 "it, use 'tahoe create-alias tahoe'.")
178 return aliases[default], path
179 if alias not in aliases:
180 raise UnknownAliasError("Unknown alias '%s', please create it with 'tahoe add-alias' or 'tahoe create-alias'." % alias)
181 return aliases[alias], path[colon+1:]
183 def escape_path(path):
184 segments = path.split("/")
185 return "/".join([urllib.quote(unicode_to_url(s)) for s in segments])