PyXMake Developer Guide: src/PyXMake/Plugin/__git.py Source File

| PyXMake Developer Guide 1.0 PyXMake

Loading...
Searching...
No Matches
__git.py
1# -*- coding: utf-8 -*-
2# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3# % GIT wrapper module - Classes and functions %
4# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5"""
6GIT configuration and management assistance wrapper.
7
8@note:
9Created on 08.08.2022
10
11@version: 1.0
12----------------------------------------------------------------------------------------------
13@requires:
14 -
15
16@change:
17 -
18
19@author: garb_ma [DLR-FA,STM Braunschweig]
20----------------------------------------------------------------------------------------------
21"""
22import os
23import sys
24import git
25import shlex
26import argparse
27import subprocess
28
29try: from urllib.parse import urlparse #@UnusedImport
30except: from urlparse import urlparse #@UnresolvedImport @Reimport
31
32 def setup():
33 """
34 GIT configuration helper interface
35 """
36 # All variables
37 __commands = []
38 __settings_check = [os.getenv("GIT_USER",""), os.getenv("GIT_PASSWORD","")]
39 # Check if the current path is a GIT repository
40 if os.path.exists(".git"):
41 # Do not execute configuration more than once
42 if os.path.exists(os.path.expanduser("~/.gitconfig_old")): return
43 # Reset all settings
44 with open(os.path.expanduser("~/.gitconfig"), mode='a'): pass
45 os.replace(os.path.expanduser("~/.gitconfig"),os.path.expanduser("~/.gitconfig_old"))
46 # Define all commands
47 __commands = ["git config --global pull.ff only",
48 "git config --global http.sslverify false",
49 "git config --global core.ignorecase false",
50 "git config --global credential.helper %s" % ("wincred" if os.name.lower() in ["nt"] else "cache",)]
51 # Add user credentials (if available)
52 if all(__settings_check):
53 __commands.extend(['git config --global user.name "%s"' % os.getenv("GIT_USER"),
54 'git config --global user.password "%s"' % os.getenv("GIT_PASSWORD")])
55 # We are running this script within a GitLab runner.
56 __settings_check.extend([os.getenv("CI_SERVER_URL","")])
57 # Check if script is executed within a GitLab runner.
58 if len(__settings_check) > 2 and all(__settings_check):
59 __commands.extend(['git config --global url."%s://%s:%s@%s/".insteadOf "%s/"' % (
60 str(urlparse(os.getenv("CI_SERVER_URL")).scheme),
61 os.getenv("GIT_USER"), os.getenv("GIT_PASSWORD"),
62 str(urlparse(os.getenv("CI_SERVER_URL")).netloc),
63 os.getenv("CI_SERVER_URL"), )])
64 # Only execute this part on Linux
65 if not os.name.lower() in ["nt"]:
66 # Verify that LFS support is enabled.
67 for x in ["apt-get update","apt-get install -y git-lfs"][::-1]: __commands.insert(0,x)
68 # Execute all commands
69 for command in __commands:
70 subprocess.call(shlex.split(command,posix=not os.name.lower() in ["nt"]),stderr=sys.stderr, stdout=sys.stdout)
71 pass
72
73 def update():
74 """
75 GIT pull command with recursive submodule and LFS support
76 """
77 # All variables
78 __commands = []
79 __settings_check = [ os.getenv("GIT_USER",""), os.getenv("GIT_PASSWORD",""), os.getenv("CI_SERVER_URL","") ]
80 # Execute GIT configuration function
81 if not os.path.exists("~/.gitconfig_old"): setup()
82 # Check if the current path is a GIT repository
83 if os.path.exists(".git"):
84 __commands = ["git lfs install","git submodule sync --recursive"]
85 # Check if script is executed within a GitLab runner.
86 if all(__settings_check):
87 __commands.extend(["""git submodule foreach --recursive 'git config --local url."%s://%s:%s@%s/".insteadOf "%s/"'""" % (
88 str(urlparse(os.getenv("CI_SERVER_URL")).scheme),
89 os.getenv("GIT_USER"), os.getenv("GIT_PASSWORD"),
90 str(urlparse(os.getenv("CI_SERVER_URL")).netloc),
91 os.getenv("CI_SERVER_URL"), )])
92 # Execute all checkout commands
93 for command in __commands:
94 subprocess.call(shlex.split(command,posix=not os.name.lower() in ["nt"]),stderr=sys.stderr, stdout=sys.stdout)
95 # Pull latest revision for each submodule
96 g = git.Repo(os.getcwd())
97 # Try to catch the current active branch
98 try: branch = str(g.active_branch.name)
99 except: branch = "HEAD"
100 # Also pull latest changes in the main directory.
101 g.git.pull("origin",branch)
102 # Also pull latest changes in the main directory.
103 g.git.pull("origin",branch)
104 # Solving dependencies w/o detached head.
105 try: g.git.submodule('update', '--init', "--recursive")
106 # Fail gracefully, which happens when all submodules are already initiased.
107 except: pass
108 # Fixing detached head during recursive dependency resolving.
109 try: g.git.submodule('update', '--init', "--recursive","--remote")
110 except: pass
111 finally: g.git.submodule('foreach','--recursive',"git pull origin $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master) || git pull origin main")
112 # Download all LFS data blobs
113 try: os.replace(os.path.expanduser("~/.gitconfig"),os.path.expanduser("~/.gitlfs"))
114 except: pass
115 # Use credential helper for backwards compatibility.
116 if all(__settings_check) and any(__commands):
117 cache = """-c credential.helper='!f() { sleep 1; echo "username=%s"; echo "password=%s"; }; f'""" % (os.getenv("GIT_USER"),os.getenv("GIT_PASSWORD"),)
118 else: cache = ""
119 try: g.git.submodule('foreach','--recursive',"git %s lfs pull" % cache)
120 except: pass
121 try:
122 # Has no effect on NT systems
123 os.replace(os.path.expanduser("~/.gitlfs"),os.path.expanduser("~/.gitconfig"))
124 os.replace(os.path.expanduser("~/.gitconfig_old"),os.path.expanduser("~/.gitconfig"))
125 # Configuration file is empty.
126 if os.stat( os.path.expanduser("~/.gitconfig") ).st_size == 0: os.remove(os.path.expanduser("~/.gitconfig"))
127 except: pass
128 pass
129
130 def main(**kwargs):
131 """
132 Main command line parser.
133 """
134 if not kwargs.get("method",""):
135 parser = argparse.ArgumentParser(description='CLI wrapper options for GIT.')
136 parser.add_argument('method', metavar='option', type=str, nargs=1,
137 help='An option identifier. Either <setup> or <update>. All other CLI arguments are directly parsed to GIT.')
138 # Select method
139 args, _ = parser.parse_known_args()
140 method = str(args.method[0])
141 else: method = kwargs.get("method")
142 # Execute wrapper within this script or parse the command to git
143 command = " ".join(["git"] + sys.argv[1:])
144 # Internal command shall always take precedence
145 if not method in globals() or ( len(sys.argv[1:]) > 1 and not method in globals() ):
146 subprocess.call(shlex.split(command,posix=not os.name.lower() in ["nt"]),stderr=sys.stderr, stdout=sys.stdout)
147 else: globals()[method]()
148 pass
149
150if __name__ == "__main__":
151 pass
PyXMake.Plugin.__git.update
update()
Definition __git.py:73
PyXMake.Plugin.__git.setup
setup()
Definition __git.py:32
PyXMake.Plugin.main
main()
Provide a custom error handler for the interruption event triggered by this wrapper to prevent multip...
Definition __init__.py:62