]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/scripts/common.py
cli: decode all cli arguments, assuming that they are utf-8 encoded
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / scripts / common.py
1
2 import os, sys, urllib
3 from twisted.python import usage
4
5
6 class BaseOptions:
7     # unit tests can override these to point at StringIO instances
8     stdin = sys.stdin
9     stdout = sys.stdout
10     stderr = sys.stderr
11
12     optFlags = [
13         ["quiet", "q", "Operate silently."],
14         ["version", "V", "Display version numbers and exit."],
15         ]
16
17     def opt_version(self):
18         import allmydata
19         print allmydata.get_package_versions_string()
20         sys.exit(0)
21
22
23 class BasedirMixin:
24     optFlags = [
25         ["multiple", "m", "allow multiple basedirs to be specified at once"],
26         ]
27
28     def postOptions(self):
29         if not self.basedirs:
30             raise usage.UsageError("<basedir> parameter is required")
31         if self['basedir']:
32             del self['basedir']
33         self['basedirs'] = [os.path.abspath(os.path.expanduser(b))
34                             for b in self.basedirs]
35
36     def parseArgs(self, *args):
37         self.basedirs = []
38         if self['basedir']:
39             self.basedirs.append(self['basedir'])
40         if self['multiple']:
41             self.basedirs.extend(args)
42         else:
43             if len(args) == 0 and not self.basedirs:
44                 if sys.platform == 'win32':
45                     from allmydata.windows import registry
46                     self.basedirs.append(registry.get_base_dir_path())
47                 else:
48                     self.basedirs.append(os.path.expanduser("~/.tahoe"))
49             if len(args) > 0:
50                 self.basedirs.append(args[0])
51             if len(args) > 1:
52                 raise usage.UsageError("I wasn't expecting so many arguments")
53
54 class NoDefaultBasedirMixin(BasedirMixin):
55     def parseArgs(self, *args):
56         # create-client won't default to --basedir=~/.tahoe
57         self.basedirs = []
58         if self['basedir']:
59             self.basedirs.append(self['basedir'])
60         if self['multiple']:
61             self.basedirs.extend(args)
62         else:
63             if len(args) > 0:
64                 self.basedirs.append(args[0])
65             if len(args) > 1:
66                 raise usage.UsageError("I wasn't expecting so many arguments")
67         if not self.basedirs:
68             raise usage.UsageError("--basedir must be provided")
69
70 DEFAULT_ALIAS = "tahoe"
71
72
73 def get_aliases(nodedir):
74     from allmydata import uri
75     aliases = {}
76     aliasfile = os.path.join(nodedir, "private", "aliases")
77     rootfile = os.path.join(nodedir, "private", "root_dir.cap")
78     try:
79         f = open(rootfile, "r")
80         rootcap = f.read().strip()
81         if rootcap:
82             aliases["tahoe"] = uri.from_string_dirnode(rootcap).to_string()
83     except EnvironmentError:
84         pass
85     try:
86         f = open(aliasfile, "r")
87         for line in f.readlines():
88             line = line.strip()
89             if line.startswith("#") or not line:
90                 continue
91             name, cap = line.split(":", 1)
92             # normalize it: remove http: prefix, urldecode
93             cap = cap.strip()
94             aliases[name] = uri.from_string_dirnode(cap).to_string()
95     except EnvironmentError:
96         pass
97     return aliases
98
99 class DefaultAliasMarker:
100     pass
101
102 def get_alias(aliases, path, default):
103     # transform "work:path/filename" into (aliases["work"], "path/filename").
104     # If default=None, then an empty alias is indicated by returning
105     # DefaultAliasMarker. We special-case "URI:" to make it easy to access
106     # specific files/directories by their read-cap.
107     path = path.strip()
108     if path.startswith("URI:"):
109         # The only way to get a sub-path is to use URI:blah:./foo, and we
110         # strip out the :./ sequence.
111         sep = path.find(":./")
112         if sep != -1:
113             return path[:sep], path[sep+3:]
114         return path, ""
115     colon = path.find(":")
116     if colon == -1:
117         # no alias
118         if default == None:
119             return DefaultAliasMarker, path
120         return aliases[default], path
121     alias = path[:colon]
122     if "/" in alias:
123         # no alias, but there's a colon in a dirname/filename, like
124         # "foo/bar:7"
125         if default == None:
126             return DefaultAliasMarker, path
127         return aliases[default], path
128     return aliases[alias], path[colon+1:]
129
130 def escape_path(path):
131     segments = path.split("/")
132     return "/".join([urllib.quote(s.encode('utf-8')) for s in segments])