def _get(): if id: logger.info(f"Query release: {id}") logger.info(f"Owner:\t{owner}") logger.info(f"Repo:\t{repo}") logger.info("Waiting...") code, data = r.get_release(owner, repo, id) if code != 200: utils.print_failed() logger.error(repo.get("message")) ctx.exit() data.pop('author') utils.print_dict(data) else: logger.info("Query releases") logger.info(f"Owner:\t{owner}") logger.info(f"Repo:\t{repo}") logger.info("Waiting...") code, data = r.get_releases(owner, repo) if code != 200: utils.print_failed() logger.error(repo.get("message")) ctx.exit() utils.print_list(data, *['id', 'name', 'tag_name']) logger.info('Now you can see the detail with command:') logger.info('\t\tgoss-cli release <id>') utils.print_success() ctx.exit()
def login(ctx, user, password, yes): g = ctx.obj confirm = utils.make_error_msg('The login information already exists. Do you want to replace it?') if not yes: # 判断已经登录过,是否替换登录信息 if g and not click.confirm(confirm): return conf = configparser.ConfigParser() conf['default'] = dict(user = user, password = password) g = Github(user, password) code, data = g.get_user_info() if code != 200: utils.print_failed() logger.error('用户名或密码错误') return owner = data.get("name") conf['default']['owner'] = owner with open(GOSS_CREDENTIAL_PATH, 'w') as f: conf.write(f) with open(GOSS_USER_INFO_PATH, 'w') as f: f.write(json.dumps(data, indent = 4)) f.flush() f.close() conf_data = dict(name = owner) email = data.get("email") if email: conf_data['email'] = email utils.config(GOSS_CONFIG_PATH, 'user', **conf_data) utils.print_success() logger.info('Name :', owner) logger.info('Email :', email)
def config(ctx, name, value): ''' Get/Create/Update goss config goss-cli config : Show config goss-cli config user.name wxnacy : Create/Update config value ''' if name and value and '.' in name: names = name.split('.') section = names[0] key = names[1] utils.config(GOSS_CONFIG_PATH, section, **{key: value}) utils.print_success() return conf = configparser.ConfigParser() conf.read(GOSS_CONFIG_PATH) secs = conf.sections() for sec in secs: click.echo('[{}]'.format(sec)) kv = conf[sec] for k, v in kv.items(): click.echo(' {} = {}'.format(k, v))
def create(g, filepath, path=None, repo=None, yes=False, **kw): ''' 创建文件 ''' r = g.get_release() # print(g._user) owner = g.owner if kw.get("config"): g.config.read(kw['config']) if not path: path = g.config.repo.path if not path: path = os.path.basename(filepath) if path.endswith('/'): path += os.path.basename(filepath) if not repo: repo = g.config.repo.name def _upload_asset(): '''上传 release 的资产''' name = kw.get("name") if not name: name = os.path.basename(filepath) logger.info('Upload asset') logger.info('Release\t:', release) logger.info('Source\t:', filepath) # logger.info('Path\t:', path) download_url = f'https://github.com/{owner}/{repo}/releases/download/{release}/{name}' html_url = f'https://github.com/{owner}/{repo}/blob/master/{path}' # logger.info('HtmlUrl\t:', html_url) logger.info('DownUrl\t:', click.style(download_url, fg='blue')) pyperclip.copy(download_url) logger.info( 'Now you can use it with {} and wait for the upload to succeed.'. format(click.style('<CTRL-V>', fg='blue'))) logger.info('Waiting...') code, data = r.get_release_by_tag(owner, repo, release) if code == 404: utils.print_failed() logger.error('Release not found', with_color=True) sys.exit(0) release_id = data.get("id") code, data = r.upload_asset_from_path(owner, repo, release_id, filepath, name) if code != 201: utils.print_failed() utils.print_error(data['message']) for err in data.get('errors', []): utils.print_error(f"\t- {err['field']} {err['code']}") sys.exit(0) release = kw.get('release') if release: _upload_asset() else: upload_file(g, owner, repo, filepath, path, yes) utils.print_success()
def repo(g, ctx, name, orga, method): ''' Get/Create your repositorys ''' if name and '/' in name: orga = name.split('/')[0] name = name.split('/')[1] owner = orga if orga else g.owner method = method.lower() if method == 'get': # 处理 get 请求 if name: # 获取单个 repository logger.info('Query repository {}/{}'.format(owner, name)) logger.info('Waiting...') code, repo = g.get_repository(owner, name) if code != 200: utils.print_failed() logger.error(repo.get("message")) ctx.exit() utils.print_dict(repo, ['owner']) utils.print_success() ctx.exit() # 获取全部 repositorys logger.info('Query your repositorys.') logger.info('Waiting...') code, repos = g.get_owner_repositorys() if code != 200: utils.print_failed() logger.error(repo.get("message")) ctx.exit() utils.print_list(repos, *['id', 'name', 'full_name', 'url']) utils.print_success() ctx.exit() elif method == 'post': logger.info("Create repository") logger.info("Url : https://github.com/{}/{}".format(owner, name)) logger.info('Waiting...') code, data = g.create_repository(name) if code != 201: utils.print_failed() logger.error(data.get("message")) logger.info("Create README.md") logger.info("Url : https://github.com/{}/{}/blob/master/README.md".format(owner, name)) logger.info('Waiting...') code, data = g.create_file_from_url(owner, name, 'https://raw.githubusercontent.com/wxnacy/goss/master/create_readme.md', 'README.md') if code != 201: utils.print_failed() logger.error(data.get("message")) utils.print_success() elif method == 'delete': logger.info("Delete repository") logger.info("Url : https://github.com/{}/{}".format(owner, name)) logger.info('Waiting...') code, data = g.delete_repository(owner, name) if code == 204: utils.print_success() else: utils.print_failed() logger.error(data.get("message"))
def file(g, ctx, repo, path, orga, method, download, output, yes): ''' Get/Delete/Download your file If you want to upload file. Please use command goss <filepath> --repo=<repository-name> More usage see : goss --help ''' owner = orga if orga else g.owner repo = repo if repo else g.config.repo.name # def _get_progress(progress, total): # '''打印进度条''' # progress_ratio = progress / total # progress_len = 20 # progress_num = int(progress_ratio * 20) # pro_text = '[{:-<20s}] {:.2f}% {} / {}'.format( # '=' * progress_num, progress_ratio * 100, progress, total) # return pro_text # def _save(p, filepath, content): # '''保存文件''' # byte_data = base64.b64decode(content.encode()) # _save_by_bytes(p, filepath, byte_data) # def _save_by_bytes(p, filepath, byte_data): # '''保存文件''' # filedir = os.path.dirname(filepath) # filename = os.path.dirname(filepath) # with open(name, 'wb') as f: # total = len(byte_data) # progress = 0 # step = 10 # while progress < total: # b = progress # e = b + step # f.write(byte_data[b:e]) # progress += step # end = '\r' # if progress >= total: # end = '\n' # progress = total # print(p, _get_progress(progress, total), end = end) # f.flush() # f.close() # if download: # logger.info('Download file') # logger.info('Owner\t: {}'.format(owner)) # logger.info('Repo\t: {}'.format(repo)) # logger.info('Path\t: {}'.format(path)) # logger.info('Waiting...') # code, data = g.get_file(owner, repo, path) # if code == 403: # 文件太大,需要使用其它方式进行下载 # logger.warn('The file is larger than 1 MB and needs to be downloaded using the download_url.') # path_dir = os.path.dirname(path) # if not path_dir: # path_dir = '/' # c, files = g.get_file(owner, repo, path_dir) # down_url = '' # file_name = [] # for f in files: # if f['path'] == path: # down_url = f['download_url'] # file_name = f['name'] # file_res = requests.get(down_url) # name = output or file_name # _save_by_bytes(path, name, file_res.content) # utils.print_success() # ctx.exit() # if code != 200: # 其他错误直接返回 # utils.print_failed() # logger.error(data.get("message")) # ctx.exit() # type = data.get("type") # name = output or data.get("name") # if isinstance(data, dict): # content = data.get("content") # _save(path, name, content) # elif isinstance(data, list): # pass # utils.print_success() # ctx.exit() def _print_file_list(lines): '''打印文件列表信息''' max_size_len = 0 max_path_len = 0 for l in lines: max_size_len = max(max_size_len, len(str(l['size']))) l['path'] = reprlib.repr(l['path'].replace(path, '').replace('/', '')).strip('\'') max_path_len = max(max_path_len, utils.charlen(l['path'])) title = 'Title\t{}\t{}\tDownloadUrl'.format('Size'.ljust(max_size_len), 'Path'.ljust(max_path_len)) hor_len = len(title) + 50 hor_line = click.style('-' * hor_len, fg='yellow') click.secho(title, fg='magenta') click.secho(hor_line) for l in lines: size = str(l['size']).ljust(max_size_len) l['size'] = size l['path'] = utils.charljust(l['path'], max_path_len) # l['path'] = l['path'].ljust(max_path_len, '*') line = '{type}\t{size}\t{path}\t{download_url}'.format(**l) click.echo(line) click.secho(hor_line) total = click.style(str(len(data)), fg='cyan') click.secho(f'Total : {total}') click.echo('') def fmt_list(data): for l in data: l['path'] = reprlib.repr(l['path'].replace(path, '').replace('/', '')).strip('\'') def print_data(data): '''打印文件信息''' if isinstance(data, list): # 打印列表 # _print_file_list(data) fmt_list(data) utils.print_list(data, 'type', 'size', 'path', 'download_url') elif isinstance(data, dict): # 打印单个文件 utils.print_dict(data, exclude=['_links', 'content']) try: pyperclip.copy(data['download_url']) except: pass logger.info('Now you can use download_url with {}.'.format( click.style('<CTRL-V>', fg='blue') )) def _del_file(path, sha): '''删除单个文件''' code, data = g.delete_file(owner, repo, path, sha) if code != 200: utils.print_failed() logger.error(path, filedata.get("message")) ctx.exit() logger.info(path, 'deleted') method = method.lower() if method == 'get': # 处理 get 请求 logger.info('Query file') logger.info('Owner\t: {}'.format(owner)) logger.info('Repo\t: {}'.format(repo)) logger.info('Path\t: {}'.format(path)) logger.info('Waiting...') code, data = g.get_file(owner, repo, path) if code == 200: print_data(data) utils.print_success() else: utils.print_failed() logger.error(data.get("message")) elif method == 'delete': logger.info('Delete file') logger.info('Owner\t: {}'.format(owner)) logger.info('Repo\t: {}'.format(repo)) logger.info('Path\t: {}'.format(path)) logger.info('Waiting...') code, filedata = g.get_file(owner, repo, path) if code != 200: utils.print_failed() logger.error(filedata.get("message")) ctx.exit() if isinstance(filedata, list): # 删除文件夹 if not yes: # 确认是否删除 if not click.confirm('The {} is a folder, are you sure to delete?'.format(path)): ctx.exit() else: logger.warn('The {} is a folder and is now being deleted'.format(path), with_color=True) for f in filedata: _del_file(f['path'], f['sha']) elif isinstance(filedata, dict): # 删除文件 sha = filedata.get("sha") _del_file(path, sha) utils.print_success()