Last active
September 12, 2019 13:09
-
-
Save nkmathew/f34689f1ff9d11c578f17c63d36ebaf3 to your computer and use it in GitHub Desktop.
Backup those reference projects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
r""" | |
Author: nkmathew <kipkoechmathew@gmail.com> | |
Date: April 29, 2016 | |
The script generates a list of all the reference git repos in a certain folder and | |
its subfolders should you need to reclone them later in the same structure | |
e.g | |
$ tree /a workspace | |
C:\Users\nkmathew\workspace\ | |
\---projects | |
\---vuejs-projects | |
+---markdown-editor-vuejs | |
+---notes-app-vuejs-vuex | |
\---vueify-example | |
$ gitfolders.py | |
#!/usr/bin/env bash | |
git clone http://www.github.com/coligo-io/markdown-editor-vuejs projects/vuejs-projects/markdown-editor-vuejs $* | |
printf "\n" | |
git clone https://github.com/coligo-io/notes-app-vuejs-vuex projects/vuejs-projects/notes-app-vuejs-vuex $* | |
printf "\n" | |
git clone https://github.com/vuejs/vueify-example projects/vuejs-projects/vueify-example $* | |
printf "\n" | |
You'd simply rerun the script when you move to a new installation instead of looking | |
up the project names on github and cloning them one by one. | |
### CHANGELOG | |
+ Jul 18, 2017 | |
- Replace http with https urls so you don't get prompted for a password | |
""" | |
import argparse | |
import os | |
import subprocess | |
import sys | |
# pylint: disable=unused-import | |
from pprint import pprint | |
__version__ = '0.1.0' | |
SHEBANG = '#!/usr/bin/env bash\n\n' | |
def create_args_parser(): | |
""" Returns command line parser """ | |
parser = argparse.ArgumentParser( | |
description="Generates a batch/shell script that reclones all the git" | |
"folders in the current folder", | |
prog='gitfolders') | |
parser.add_argument( | |
'-o', '--out-file', dest='script_name', | |
help='Name/path of generated bash file') | |
parser.add_argument( | |
'-urls-only', '--urls-only', dest='urls_only', | |
help='Generates the Git repo urls only instead of the commands') | |
parser.add_argument( | |
'-v', '--version', action='version', | |
help='Prints script version', version='gitfolders v%s' % __version__) | |
parser.add_argument('folders', help='List of files to be walked. ' | |
'Defaults to current directory if none is provided', | |
nargs='*') | |
return parser | |
def parse_options(arguments=None): | |
""" Reads command-line arguments | |
""" | |
if arguments is None: | |
arguments = sys.argv[1:] | |
if isinstance(arguments, str): | |
arguments = arguments.split() | |
if isinstance(arguments, argparse.Namespace): | |
return arguments | |
parser = create_args_parser() | |
args = parser.parse_args(arguments) | |
if not args.folders: | |
args.folders = [x for x in os.listdir('.') if not x.startswith('.') and | |
os.path.isdir(x)] | |
return args | |
def git_folders(parent_folder='.'): | |
""" | |
Returns a list of all root git subfolders together with their urls | |
>>> git_folders('.') | |
[('mine\\repos\\yasi-sexp-indenter', | |
'C:\\users\\nkmathew\\workspace\\projects\\mine\\repos\\yasi-sexp-indenter', | |
u'git@github.com:nkmathew/yasi-sexp-indenter.git'), | |
('mine\\sql-app', | |
'C:\\users\\nkmathew\\workspace\\projects\\mine\\sql-app', | |
u'https://hub.jazz.net/git/nkmathew/sql-app')] | |
""" | |
root_folders = [] | |
parent_folder = os.path.normpath(parent_folder) | |
for dirpath, subfolders, _ in os.walk(parent_folder): | |
rel_path = os.path.relpath(dirpath) | |
if '.git' in subfolders: | |
# Found root of a git folder, ignore all subfolders and move on to | |
# the other directories | |
subfolders[:] = [] | |
git_dir = os.path.join(dirpath, '.git') | |
if os.path.exists(git_dir): | |
remote_url = '' | |
try: | |
remote_url = subprocess.check_output( | |
['git', '--git-dir', git_dir, | |
'config', '--get', 'remote.origin.url'], | |
stderr=subprocess.STDOUT).decode('utf8') | |
except subprocess.CalledProcessError: | |
pass | |
if remote_url: | |
remote_url = remote_url.strip().replace('http:', 'https:') | |
root_folders += [(rel_path, dirpath, remote_url)] | |
return root_folders | |
def clone_command_list(parent='.'): | |
r""" | |
Builds clone commands | |
>>> clone_command_list('C:/users/nkmathew/workspace/projects/mine/') | |
['git clone git@gist.github.com:2c21aa3dbb9d69d49549.git mine\gists\fdups', | |
'git clone git@gist.github.com:43aec97134a204a5228d.git mine\gists\githubclone.py', | |
'git clone git@gist.github.com:b8d5da192f8862886017.git mine\gists\gmail-agecounter', | |
'git clone git@gist.github.com:15501728a6a77fee7ba4.git mine\gists\gmail-delete', | |
...] | |
""" | |
folder_list = git_folders(parent) | |
commands = [] | |
for folder in folder_list: | |
clone_url = folder[2] | |
dest_path = folder[0] | |
if os.sep == '\\': | |
dest_path = dest_path.replace('\\', '/') | |
cmd = 'git clone ' + clone_url + ' ' + dest_path | |
commands += [cmd] | |
return commands | |
def build_commands(parent='.'): | |
""" | |
Simply concatenates the command lines | |
""" | |
commands = clone_command_list(parent) | |
commands += [''] # Beware of joins on a single item list | |
return ' $*\nprintf "\\n"\n'.join(commands) | |
def main(options=None): | |
""" | |
Entry point | |
""" | |
opts = parse_options(options) | |
full_script = '' | |
for folder in opts.folders: | |
if opts.urls_only: | |
url_list = git_folders(folder) | |
url_list = [x[2] for x in url_list] | |
url_list += [''] | |
full_script += '\n'.join(url_list) | |
else: | |
script = '\n# %s\n\n' % folder | |
script += build_commands(folder) | |
full_script += script | |
full_script = SHEBANG + full_script | |
if opts.script_name: | |
with open(opts.script_name, 'wb') as outfile: | |
outfile.write(full_script.encode('utf8')) | |
else: | |
print(full_script) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment