-
-
Save rsrini7/06d25108075e0270a88318899819d257 to your computer and use it in GitHub Desktop.
Backup those reference projects gitfolders
This file contains hidden or 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 <[email protected]>, Srini | |
Date: April 29, 2016 | |
Date: Sept 12, 2019 | |
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 | |
Removed printf | |
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'[email protected]: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 [email protected]:2c21aa3dbb9d69d49549.git mine\gists\fdups', | |
'git clone [email protected]:43aec97134a204a5228d.git mine\gists\githubclone.py', | |
'git clone [email protected]:b8d5da192f8862886017.git mine\gists\gmail-agecounter', | |
'git clone [email protected]: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 ' \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