-
Notifications
You must be signed in to change notification settings - Fork 0
/
ConfigDiff.py
138 lines (112 loc) · 4.41 KB
/
ConfigDiff.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
ConfigDiffReports
A Tool to report on the configuration changes that have happened in the last week
and gather the commit info that happened for the repo
"""
__author__ = "Ajaydeep Singh / [email protected]"
__version__ = "0.1.0"
import argparse
import logging
import git
from git import Repo
import os
import os.path as osp
DATE_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S%z"
EMPTY_TREE_SHA = "4b825dc642cb6eb9a060e54bf8d69288fbee4904" # Github secret empty tree SHA
join = osp.join
path = "/Users/asingh/Github/device_config" # local path of repo you want to report diffs on
diffStats = [] # Initialize list for commit information
def main():
"""Entry point of the app."""
logging.basicConfig(filename='debug.log', level=logging.DEBUG)
WEEK = 355
for x in versions(path):
diffStats.append(x)
current = diffStats[0] # Get latest commit
weekago = diffStats[WEEK] # Get commit from a week ago
twoweeksago = diffStats[WEEK*2]
# initialize the Repo object to use for git diff
repo = git.Repo(path)
# Create file for .diff
f = open('week.diff','w')
# print out diff to file
f.write(repo.git.diff(current['commit'], weekago['commit'], exclude='*.cfg'))
f.close
# Create file for .diff
f = open('twoweek.diff', 'w')
# print out diff to file
f.write(repo.git.diff(current['commit'], twoweeksago['commit'], exclude='*.cfg'))
f.close
def versions(path, branch='master'):
"""This function returns a generator which iterates through all commits of
the repository located in the given path for the given branch. It yields
file diff information to show a timeseries of file changes."""
repo = git.Repo(path)
# Iterate through every commit for the given branch in the repository
for commit in repo.iter_commits(branch):
parent = commit.parents[0] if commit.parents else EMPTY_TREE_SHA
diffs = {
diff.a_path: diff for diff in commit.diff(parent)
}
# The stats on the commit is a summary of all the changes for this
# commit, we'll iterate through it to get the information we need.
for objpath, stats in commit.stats.files.items():
# Select the diff for the path in the stats
diff = diffs.get(objpath)
# If the path is not in the dictionary, it's because it was
# renamed, so search through the b_paths for the current name.
if not diff:
for diff in diffs.values():
if diff.b_path == path and diff.renamed:
break
# Update the stats with the additional information
stats.update({
'object': os.path.join(path, objpath),
'commit': commit.hexsha,
'author': commit.author.email,
'timestamp': commit.authored_datetime.strftime(DATE_TIME_FORMAT),
'size': diff_size(diff),
'type': diff_type(diff),
})
yield stats
def diff_size(diff):
"""
Computes the size of the diff by comparing the size of the blobs.
"""
if diff.b_blob is None and diff.deleted_file:
return diff.a_blob.size * -1
if diff.a_blob is None and diff.new_file:
return diff.b_blob.size
# Otherwise just return the size a-b
return diff.a_blob.size - diff.b_blob.size
def diff_type(diff):
"""
Determines the type of the diff by looking at the diff flags.
"""
if diff.renamed: return 'R'
if diff.deleted_file: return 'D'
if diff.new_file: return 'A'
return 'M'
# Dont really need an argparse
# This is all boilerplate for argparse if its needed down the line
if __name__ == "__main__":
# parser = argparse.ArgumentParser()
# parser.add_argument("arg", help="Required positional argument")
# parser.add_argument("-f", "--flag", action="store_true", default=False)
# parser.add_argument("-n", "--name", action="store", dest="name")
# # Optional verbosity counter (eg. -v, -vv, -vvv, etc.)
# parser.add_argument(
# "-v",
# "--verbose",
# action="count",
# default=0,
# help="Verbosity (-v, -vv, etc)")
# # Specify output of "--version"
# parser.add_argument(
# "--version",
# action="version",
# version="%(prog)s (version {version})".format(version=__version__))
# args = parser.parse_args()
main()