##// END OF EJS Templates
Change command line tool config location to .config/kallithea
Bradley M. Kuhn -
r4181:e5cb0a4e kallithea-2.2.5-r...
parent child Browse files
Show More
@@ -1,27 +1,26 b''
1 syntax: glob
1 syntax: glob
2 *.pyc
2 *.pyc
3 *.swp
3 *.swp
4 *.sqlite
4 *.sqlite
5 *.tox
5 *.tox
6 *.egg-info
6 *.egg-info
7 *.egg
7 *.egg
8
8
9 syntax: regexp
9 syntax: regexp
10 ^rcextensions
10 ^rcextensions
11 ^build
11 ^build
12 ^dist/
12 ^dist/
13 ^docs/build/
13 ^docs/build/
14 ^docs/_build/
14 ^docs/_build/
15 ^data$
15 ^data$
16 ^sql_dumps/
16 ^sql_dumps/
17 ^\.settings$
17 ^\.settings$
18 ^\.project$
18 ^\.project$
19 ^\.pydevproject$
19 ^\.pydevproject$
20 ^\.coverage$
20 ^\.coverage$
21 ^rhodecode\.db$
21 ^rhodecode\.db$
22 ^test\.db$
22 ^test\.db$
23 ^RhodeCode\.egg-info$
23 ^RhodeCode\.egg-info$
24 ^rc.*\.ini$
24 ^rc.*\.ini$
25 ^fabfile.py
25 ^fabfile.py
26 ^\.rhodecode$
27 ^\.idea$
26 ^\.idea$
@@ -1,167 +1,167 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # This program is free software: you can redistribute it and/or modify
2 # This program is free software: you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation, either version 3 of the License, or
4 # the Free Software Foundation, either version 3 of the License, or
5 # (at your option) any later version.
5 # (at your option) any later version.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU General Public License
12 # You should have received a copy of the GNU General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 """
14 """
15 rhodecode.bin.base
15 rhodecode.bin.base
16 ~~~~~~~~~~~~~~~~~~
16 ~~~~~~~~~~~~~~~~~~
17
17
18 Base utils for shell scripts
18 Base utils for shell scripts
19
19
20 :created_on: May 09, 2013
20 :created_on: May 09, 2013
21 :author: marcink
21 :author: marcink
22 :copyright: (c) 2013 RhodeCode GmbH.
22 :copyright: (c) 2013 RhodeCode GmbH.
23 :license: GPLv3, see LICENSE for more details.
23 :license: GPLv3, see LICENSE for more details.
24 """
24 """
25
25
26 import os
26 import os
27 import sys
27 import sys
28 import random
28 import random
29 import urllib2
29 import urllib2
30 import pprint
30 import pprint
31
31
32 try:
32 try:
33 from rhodecode.lib.ext_json import json
33 from rhodecode.lib.ext_json import json
34 except ImportError:
34 except ImportError:
35 try:
35 try:
36 import simplejson as json
36 import simplejson as json
37 except ImportError:
37 except ImportError:
38 import json
38 import json
39
39
40 CONFIG_NAME = '.rhodecode'
40 CONFIG_NAME = '.config/kallithea'
41 FORMAT_PRETTY = 'pretty'
41 FORMAT_PRETTY = 'pretty'
42 FORMAT_JSON = 'json'
42 FORMAT_JSON = 'json'
43
43
44
44
45 def api_call(apikey, apihost, method=None, **kw):
45 def api_call(apikey, apihost, method=None, **kw):
46 """
46 """
47 Api_call wrapper for RhodeCode.
47 Api_call wrapper for RhodeCode.
48
48
49 :param apikey:
49 :param apikey:
50 :param apihost:
50 :param apihost:
51 :param format: formatting, pretty means prints and pprint of json
51 :param format: formatting, pretty means prints and pprint of json
52 json returns unparsed json
52 json returns unparsed json
53 :param method:
53 :param method:
54 :returns: json response from server
54 :returns: json response from server
55 """
55 """
56 def _build_data(random_id):
56 def _build_data(random_id):
57 """
57 """
58 Builds API data with given random ID
58 Builds API data with given random ID
59
59
60 :param random_id:
60 :param random_id:
61 """
61 """
62 return {
62 return {
63 "id": random_id,
63 "id": random_id,
64 "api_key": apikey,
64 "api_key": apikey,
65 "method": method,
65 "method": method,
66 "args": kw
66 "args": kw
67 }
67 }
68
68
69 if not method:
69 if not method:
70 raise Exception('please specify method name !')
70 raise Exception('please specify method name !')
71 apihost = apihost.rstrip('/')
71 apihost = apihost.rstrip('/')
72 id_ = random.randrange(1, 9999)
72 id_ = random.randrange(1, 9999)
73 req = urllib2.Request('%s/_admin/api' % apihost,
73 req = urllib2.Request('%s/_admin/api' % apihost,
74 data=json.dumps(_build_data(id_)),
74 data=json.dumps(_build_data(id_)),
75 headers={'content-type': 'text/plain'})
75 headers={'content-type': 'text/plain'})
76 ret = urllib2.urlopen(req)
76 ret = urllib2.urlopen(req)
77 raw_json = ret.read()
77 raw_json = ret.read()
78 json_data = json.loads(raw_json)
78 json_data = json.loads(raw_json)
79 id_ret = json_data['id']
79 id_ret = json_data['id']
80 if id_ret == id_:
80 if id_ret == id_:
81 return json_data
81 return json_data
82
82
83 else:
83 else:
84 _formatted_json = pprint.pformat(json_data)
84 _formatted_json = pprint.pformat(json_data)
85 raise Exception('something went wrong. '
85 raise Exception('something went wrong. '
86 'ID mismatch got %s, expected %s | %s' % (
86 'ID mismatch got %s, expected %s | %s' % (
87 id_ret, id_, _formatted_json))
87 id_ret, id_, _formatted_json))
88
88
89
89
90 class RcConf(object):
90 class RcConf(object):
91 """
91 """
92 RhodeCode config for API
92 RhodeCode config for API
93
93
94 conf = RcConf()
94 conf = RcConf()
95 conf['key']
95 conf['key']
96
96
97 """
97 """
98
98
99 def __init__(self, config_location=None, autoload=True, autocreate=False,
99 def __init__(self, config_location=None, autoload=True, autocreate=False,
100 config=None):
100 config=None):
101 HOME = os.getenv('HOME', os.getenv('USERPROFILE')) or ''
101 HOME = os.getenv('HOME', os.getenv('USERPROFILE')) or ''
102 HOME_CONF = os.path.abspath(os.path.join(HOME, CONFIG_NAME))
102 HOME_CONF = os.path.abspath(os.path.join(HOME, CONFIG_NAME))
103 self._conf_name = HOME_CONF if not config_location else config_location
103 self._conf_name = HOME_CONF if not config_location else config_location
104 self._conf = {}
104 self._conf = {}
105 if autocreate:
105 if autocreate:
106 self.make_config(config)
106 self.make_config(config)
107 if autoload:
107 if autoload:
108 self._conf = self.load_config()
108 self._conf = self.load_config()
109
109
110 def __getitem__(self, key):
110 def __getitem__(self, key):
111 return self._conf[key]
111 return self._conf[key]
112
112
113 def __nonzero__(self):
113 def __nonzero__(self):
114 if self._conf:
114 if self._conf:
115 return True
115 return True
116 return False
116 return False
117
117
118 def __eq__(self):
118 def __eq__(self):
119 return self._conf.__eq__()
119 return self._conf.__eq__()
120
120
121 def __repr__(self):
121 def __repr__(self):
122 return 'RcConf<%s>' % self._conf.__repr__()
122 return 'RcConf<%s>' % self._conf.__repr__()
123
123
124 def make_config(self, config):
124 def make_config(self, config):
125 """
125 """
126 Saves given config as a JSON dump in the _conf_name location
126 Saves given config as a JSON dump in the _conf_name location
127
127
128 :param config:
128 :param config:
129 """
129 """
130 update = False
130 update = False
131 if os.path.exists(self._conf_name):
131 if os.path.exists(self._conf_name):
132 update = True
132 update = True
133 with open(self._conf_name, 'wb') as f:
133 with open(self._conf_name, 'wb') as f:
134 json.dump(config, f, indent=4)
134 json.dump(config, f, indent=4)
135
135
136 if update:
136 if update:
137 sys.stdout.write('Updated config in %s\n' % self._conf_name)
137 sys.stdout.write('Updated config in %s\n' % self._conf_name)
138 else:
138 else:
139 sys.stdout.write('Created new config in %s\n' % self._conf_name)
139 sys.stdout.write('Created new config in %s\n' % self._conf_name)
140
140
141 def update_config(self, new_config):
141 def update_config(self, new_config):
142 """
142 """
143 Reads the JSON config updates it's values with new_config and
143 Reads the JSON config updates it's values with new_config and
144 saves it back as JSON dump
144 saves it back as JSON dump
145
145
146 :param new_config:
146 :param new_config:
147 """
147 """
148 config = {}
148 config = {}
149 try:
149 try:
150 with open(self._conf_name, 'rb') as conf:
150 with open(self._conf_name, 'rb') as conf:
151 config = json.load(conf)
151 config = json.load(conf)
152 except IOError, e:
152 except IOError, e:
153 sys.stderr.write(str(e) + '\n')
153 sys.stderr.write(str(e) + '\n')
154
154
155 config.update(new_config)
155 config.update(new_config)
156 self.make_config(config)
156 self.make_config(config)
157
157
158 def load_config(self):
158 def load_config(self):
159 """
159 """
160 Loads config from file and returns loaded JSON object
160 Loads config from file and returns loaded JSON object
161 """
161 """
162 try:
162 try:
163 with open(self._conf_name, 'rb') as conf:
163 with open(self._conf_name, 'rb') as conf:
164 return json.load(conf)
164 return json.load(conf)
165 except IOError, e:
165 except IOError, e:
166 #sys.stderr.write(str(e) + '\n')
166 #sys.stderr.write(str(e) + '\n')
167 pass
167 pass
@@ -1,171 +1,171 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # This program is free software: you can redistribute it and/or modify
2 # This program is free software: you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation, either version 3 of the License, or
4 # the Free Software Foundation, either version 3 of the License, or
5 # (at your option) any later version.
5 # (at your option) any later version.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU General Public License
12 # You should have received a copy of the GNU General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 """
14 """
15 rhodecode.bin.rhodecode_gist
15 rhodecode.bin.rhodecode_gist
16 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17
17
18 Gist CLI client for RhodeCode
18 Gist CLI client for RhodeCode
19
19
20 :created_on: May 9, 2013
20 :created_on: May 9, 2013
21 :author: marcink
21 :author: marcink
22 :copyright: (c) 2013 RhodeCode GmbH.
22 :copyright: (c) 2013 RhodeCode GmbH.
23 :license: GPLv3, see LICENSE for more details.
23 :license: GPLv3, see LICENSE for more details.
24 """
24 """
25
25
26 from __future__ import with_statement
26 from __future__ import with_statement
27 import os
27 import os
28 import sys
28 import sys
29 import stat
29 import stat
30 import argparse
30 import argparse
31 import fileinput
31 import fileinput
32
32
33 from rhodecode.bin.base import json, api_call, RcConf, FORMAT_JSON, FORMAT_PRETTY
33 from rhodecode.bin.base import json, api_call, RcConf, FORMAT_JSON, FORMAT_PRETTY
34
34
35
35
36 def argparser(argv):
36 def argparser(argv):
37 usage = (
37 usage = (
38 "rhodecode-gist [-h] [--format=FORMAT] [--apikey=APIKEY] [--apihost=APIHOST] "
38 "rhodecode-gist [-h] [--format=FORMAT] [--apikey=APIKEY] [--apihost=APIHOST] "
39 "[--config=CONFIG] [--save-config] [GIST OPTIONS] "
39 "[--config=CONFIG] [--save-config] [GIST OPTIONS] "
40 "[filename or stdin use - for terminal stdin ]\n"
40 "[filename or stdin use - for terminal stdin ]\n"
41 "Create config file: rhodecode-gist --apikey=<key> --apihost=http://rhodecode.server --save-config"
41 "Create config file: rhodecode-gist --apikey=<key> --apihost=http://rhodecode.server --save-config"
42 )
42 )
43
43
44 parser = argparse.ArgumentParser(description='RhodeCode Gist cli',
44 parser = argparse.ArgumentParser(description='RhodeCode Gist cli',
45 usage=usage)
45 usage=usage)
46
46
47 ## config
47 ## config
48 group = parser.add_argument_group('config')
48 group = parser.add_argument_group('config')
49 group.add_argument('--apikey', help='api access key')
49 group.add_argument('--apikey', help='api access key')
50 group.add_argument('--apihost', help='api host')
50 group.add_argument('--apihost', help='api host')
51 group.add_argument('--config', help='config file path DEFAULT: ~/.rhodecode')
51 group.add_argument('--config', help='config file path DEFAULT: ~/.config/kallithea')
52 group.add_argument('--save-config', action='store_true',
52 group.add_argument('--save-config', action='store_true',
53 help='save the given config into a file')
53 help='save the given config into a file')
54
54
55 group = parser.add_argument_group('GIST')
55 group = parser.add_argument_group('GIST')
56 group.add_argument('-p', '--private', action='store_true',
56 group.add_argument('-p', '--private', action='store_true',
57 help='create private Gist')
57 help='create private Gist')
58 group.add_argument('-f', '--filename',
58 group.add_argument('-f', '--filename',
59 help='set uploaded gist filename, '
59 help='set uploaded gist filename, '
60 'also defines syntax highlighting')
60 'also defines syntax highlighting')
61 group.add_argument('-d', '--description', help='Gist description')
61 group.add_argument('-d', '--description', help='Gist description')
62 group.add_argument('-l', '--lifetime', metavar='MINUTES',
62 group.add_argument('-l', '--lifetime', metavar='MINUTES',
63 help='gist lifetime in minutes, -1 (DEFAULT) is forever')
63 help='gist lifetime in minutes, -1 (DEFAULT) is forever')
64 group.add_argument('--format', dest='format', type=str,
64 group.add_argument('--format', dest='format', type=str,
65 help='output format DEFAULT: `%s` can '
65 help='output format DEFAULT: `%s` can '
66 'be also `%s`' % (FORMAT_PRETTY, FORMAT_JSON),
66 'be also `%s`' % (FORMAT_PRETTY, FORMAT_JSON),
67 default=FORMAT_PRETTY
67 default=FORMAT_PRETTY
68 )
68 )
69 args, other = parser.parse_known_args()
69 args, other = parser.parse_known_args()
70 return parser, args, other
70 return parser, args, other
71
71
72
72
73 def _run(argv):
73 def _run(argv):
74 conf = None
74 conf = None
75 parser, args, other = argparser(argv)
75 parser, args, other = argparser(argv)
76
76
77 api_credentials_given = (args.apikey and args.apihost)
77 api_credentials_given = (args.apikey and args.apihost)
78 if args.save_config:
78 if args.save_config:
79 if not api_credentials_given:
79 if not api_credentials_given:
80 raise parser.error('--save-config requires --apikey and --apihost')
80 raise parser.error('--save-config requires --apikey and --apihost')
81 conf = RcConf(config_location=args.config,
81 conf = RcConf(config_location=args.config,
82 autocreate=True, config={'apikey': args.apikey,
82 autocreate=True, config={'apikey': args.apikey,
83 'apihost': args.apihost})
83 'apihost': args.apihost})
84 sys.exit()
84 sys.exit()
85
85
86 if not conf:
86 if not conf:
87 conf = RcConf(config_location=args.config, autoload=True)
87 conf = RcConf(config_location=args.config, autoload=True)
88 if not conf:
88 if not conf:
89 if not api_credentials_given:
89 if not api_credentials_given:
90 parser.error('Could not find config file and missing '
90 parser.error('Could not find config file and missing '
91 '--apikey or --apihost in params')
91 '--apikey or --apihost in params')
92
92
93 apikey = args.apikey or conf['apikey']
93 apikey = args.apikey or conf['apikey']
94 host = args.apihost or conf['apihost']
94 host = args.apihost or conf['apihost']
95 DEFAULT_FILENAME = 'gistfile1.txt'
95 DEFAULT_FILENAME = 'gistfile1.txt'
96 if other:
96 if other:
97 # skip multifiles for now
97 # skip multifiles for now
98 filename = other[0]
98 filename = other[0]
99 if filename == '-':
99 if filename == '-':
100 filename = DEFAULT_FILENAME
100 filename = DEFAULT_FILENAME
101 gist_content = ''
101 gist_content = ''
102 for line in fileinput.input('-'):
102 for line in fileinput.input('-'):
103 gist_content += line
103 gist_content += line
104 else:
104 else:
105 with open(filename, 'rb') as f:
105 with open(filename, 'rb') as f:
106 gist_content = f.read()
106 gist_content = f.read()
107
107
108 else:
108 else:
109 filename = DEFAULT_FILENAME
109 filename = DEFAULT_FILENAME
110 gist_content = None
110 gist_content = None
111 # little bit hacky but cross platform check where the
111 # little bit hacky but cross platform check where the
112 # stdin comes from we skip the terminal case it can be handled by '-'
112 # stdin comes from we skip the terminal case it can be handled by '-'
113 mode = os.fstat(0).st_mode
113 mode = os.fstat(0).st_mode
114 if stat.S_ISFIFO(mode):
114 if stat.S_ISFIFO(mode):
115 # "stdin is piped"
115 # "stdin is piped"
116 gist_content = sys.stdin.read()
116 gist_content = sys.stdin.read()
117 elif stat.S_ISREG(mode):
117 elif stat.S_ISREG(mode):
118 # "stdin is redirected"
118 # "stdin is redirected"
119 gist_content = sys.stdin.read()
119 gist_content = sys.stdin.read()
120 else:
120 else:
121 # "stdin is terminal"
121 # "stdin is terminal"
122 pass
122 pass
123
123
124 # make sure we don't upload binary stuff
124 # make sure we don't upload binary stuff
125 if gist_content and '\0' in gist_content:
125 if gist_content and '\0' in gist_content:
126 raise Exception('Error: binary files upload is not possible')
126 raise Exception('Error: binary files upload is not possible')
127
127
128 filename = os.path.basename(args.filename or filename)
128 filename = os.path.basename(args.filename or filename)
129 if gist_content:
129 if gist_content:
130 files = {
130 files = {
131 filename: {
131 filename: {
132 'content': gist_content,
132 'content': gist_content,
133 'lexer': None
133 'lexer': None
134 }
134 }
135 }
135 }
136
136
137 margs = dict(
137 margs = dict(
138 lifetime=args.lifetime,
138 lifetime=args.lifetime,
139 description=args.description,
139 description=args.description,
140 gist_type='private' if args.private else 'public',
140 gist_type='private' if args.private else 'public',
141 files=files
141 files=files
142 )
142 )
143
143
144 json_data = api_call(apikey, host, 'create_gist', **margs)['result']
144 json_data = api_call(apikey, host, 'create_gist', **margs)['result']
145 if args.format == FORMAT_JSON:
145 if args.format == FORMAT_JSON:
146 print json.dumps(json_data)
146 print json.dumps(json_data)
147 elif args.format == FORMAT_PRETTY:
147 elif args.format == FORMAT_PRETTY:
148 print json_data
148 print json_data
149 print 'Created %s gist %s' % (json_data['gist']['type'],
149 print 'Created %s gist %s' % (json_data['gist']['type'],
150 json_data['gist']['url'])
150 json_data['gist']['url'])
151 return 0
151 return 0
152
152
153
153
154 def main(argv=None):
154 def main(argv=None):
155 """
155 """
156 Main execution function for cli
156 Main execution function for cli
157
157
158 :param argv:
158 :param argv:
159 """
159 """
160 if argv is None:
160 if argv is None:
161 argv = sys.argv
161 argv = sys.argv
162
162
163 try:
163 try:
164 return _run(argv)
164 return _run(argv)
165 except Exception, e:
165 except Exception, e:
166 print e
166 print e
167 return 1
167 return 1
168
168
169
169
170 if __name__ == '__main__':
170 if __name__ == '__main__':
171 sys.exit(main(sys.argv))
171 sys.exit(main(sys.argv))
General Comments 0
You need to be logged in to leave comments. Login now