mirror of
https://github.com/munki/munki.git
synced 2026-05-05 11:59:18 -05:00
Fuller example implementation of GitFileRepo
This commit is contained in:
@@ -1,10 +1,133 @@
|
||||
import os
|
||||
import pwd
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from munkilib.munkirepo.FileRepo import FileRepo
|
||||
from FileRepo import FileRepo
|
||||
|
||||
|
||||
class MunkiGit(object):
|
||||
"""A simple interface for some common interactions with the git binary"""
|
||||
|
||||
def __init__(self, repo):
|
||||
self.cmd = '/usr/bin/git'
|
||||
self.git_repo_dir = os.getcwd()
|
||||
self.munki_repo_dir = repo.root
|
||||
self.args = []
|
||||
self.results = {}
|
||||
|
||||
def run_git(self, custom_args=None):
|
||||
"""Executes the git command with the current set of arguments and
|
||||
returns a dictionary with the keys 'output', 'error', and
|
||||
'returncode'. You can optionally pass an array into customArgs to
|
||||
override the self.args value without overwriting them."""
|
||||
custom_args = self.args if custom_args == None else custom_args
|
||||
proc = subprocess.Popen([self.cmd] + custom_args,
|
||||
shell=False,
|
||||
bufsize=-1,
|
||||
cwd=self.git_repo_dir,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
(output, error) = proc.communicate()
|
||||
self.results = {"output": output,
|
||||
"error": error, "returncode": proc.returncode}
|
||||
return self.results
|
||||
|
||||
def path_is_gitignored(self, a_path):
|
||||
"""Returns True if path will be ignored by Git (usually due to being
|
||||
in a .gitignore file)"""
|
||||
self.git_repo_dir = os.path.dirname(a_path)
|
||||
self.run_git(['check-ignore', a_path])
|
||||
return self.results['returncode'] == 0
|
||||
|
||||
def path_is_in_git_repo(self, a_path):
|
||||
"""Returns True if the path is in a Git repo, false otherwise."""
|
||||
self.git_repo_dir = os.path.dirname(a_path)
|
||||
self.run_git(['status', '-z', a_path])
|
||||
return self.results['returncode'] == 0
|
||||
|
||||
def commit_file_at_path(self, a_path):
|
||||
"""Commits the file at 'a_path'. This method will also automatically
|
||||
generate the commit log appropriate for the status of a_path where
|
||||
status would be 'modified', 'new file', or 'deleted'"""
|
||||
|
||||
# get the status of the file at a_path
|
||||
self.git_repo_dir = os.path.dirname(a_path)
|
||||
status_results = self.run_git(['status', a_path])
|
||||
status_output = status_results['output']
|
||||
if status_output.find("new file:") != -1:
|
||||
action = 'created'
|
||||
elif status_output.find("modified:") != -1:
|
||||
action = 'modified'
|
||||
elif status_output.find("deleted:") != -1:
|
||||
action = 'deleted'
|
||||
else:
|
||||
action = 'did something with'
|
||||
|
||||
# determine the path relative to self.munki_repo_dir
|
||||
# for the file at a_path
|
||||
itempath = a_path
|
||||
if a_path.startswith(self.munki_repo_dir):
|
||||
itempath = a_path[len(self.munki_repo_dir)+1:]
|
||||
|
||||
username = pwd.getpwuid(os.getuid()).pw_name
|
||||
|
||||
# generate the log message
|
||||
log_msg = ('%s %s \'%s\' via Munki command-line tools'
|
||||
% (username, action, itempath))
|
||||
print "Doing git commit: %s" % log_msg
|
||||
self.run_git(['commit', '-m', log_msg])
|
||||
if self.results['returncode'] != 0:
|
||||
print >> sys.stderr, "Failed to commit changes to %s" % a_path
|
||||
print >> sys.stderr, self.results['error']
|
||||
return -1
|
||||
return 0
|
||||
|
||||
def _add_remove_file_at_path(self, a_path, operation):
|
||||
"""Git adds or removes a file at a_path. operation must be either
|
||||
'add' or 'rm'"""
|
||||
if self.path_is_in_git_repo(a_path):
|
||||
if not self.path_is_gitignored(a_path):
|
||||
self.git_repo_dir = os.path.dirname(a_path)
|
||||
self.run_git([operation, a_path])
|
||||
if self.results['returncode'] == 0:
|
||||
self.commit_file_at_path(a_path)
|
||||
else:
|
||||
print >> sys.stderr, "Git error: %s" % self.results['error']
|
||||
else:
|
||||
print >> sys.stderr, "%s is not in a git repo." % a_path
|
||||
|
||||
def add_file_at_path(self, a_path):
|
||||
"""Commits a file to the Git repo."""
|
||||
self._add_remove_file_at_path(a_path, 'add')
|
||||
|
||||
def delete_file_at_path(self, a_path):
|
||||
"""Deletes a file from the filesystem and Git repo."""
|
||||
self._add_remove_file_at_path(a_path, 'rm')
|
||||
|
||||
class GitFileRepo(FileRepo):
|
||||
'''A subclass of FileRepo that does git commits for pkginfo files'''
|
||||
|
||||
def remove(self, path):
|
||||
'''Removes a file from the repo.'''
|
||||
result = os.remove(os.path.join(self.root, path))
|
||||
if result == 0:
|
||||
MunkiGit(self).delete_file_at_path(os.path.join(self.root, path))
|
||||
return result
|
||||
|
||||
def unlink(self, path):
|
||||
'''Removes a file from the repo.'''
|
||||
self.remove(path)
|
||||
|
||||
def put(self, src, dest):
|
||||
'''Copies a local file to the repo.'''
|
||||
cmd = ['/bin/cp', src, os.path.join(self.root, dest)]
|
||||
result = subprocess.call(cmd)
|
||||
if result == 0:
|
||||
MunkiGit(self).add_file_at_path(os.path.join(self.root, dest))
|
||||
return result
|
||||
|
||||
class RepoFile(object):
|
||||
def __init__(self, repo, repo_path, mode):
|
||||
self.repo = repo
|
||||
@@ -15,7 +138,7 @@ class GitFileRepo(FileRepo):
|
||||
|
||||
def __del__(self):
|
||||
if 'w' in self.repo_mode:
|
||||
print "Pretending to do a git commit on %s" % self.repo_path
|
||||
MunkiGit(self.repo).add_file_at_path(self.repo_path)
|
||||
|
||||
def read(self):
|
||||
return self.file.read()
|
||||
Reference in New Issue
Block a user