Skip to content

Instantly share code, notes, and snippets.

@rsrini7
Forked from nkmathew/gitfolders.py
Last active December 18, 2021 04:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rsrini7/06d25108075e0270a88318899819d257 to your computer and use it in GitHub Desktop.
Save rsrini7/06d25108075e0270a88318899819d257 to your computer and use it in GitHub Desktop.
Backup those reference projects gitfolders
#!/usr/bin/env python
r"""
Author: nkmathew <kipkoechmathew@gmail.com>, 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'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 ' \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