show_changes_by_file.py revision 13540
113540Sandrea.mondelli@ucf.edu#!/usr/bin/env python2.7 212893Sbrandon.potter@amd.com# 312893Sbrandon.potter@amd.com# Copyright (c) 2018 Advanced Micro Devices, Inc. 412893Sbrandon.potter@amd.com# All rights reserved. 512893Sbrandon.potter@amd.com# 612893Sbrandon.potter@amd.com# For use for simulation and test purposes only 712893Sbrandon.potter@amd.com# 812893Sbrandon.potter@amd.com# Redistribution and use in source and binary forms, with or without 912893Sbrandon.potter@amd.com# modification, are permitted provided that the following conditions are met: 1012893Sbrandon.potter@amd.com# 1112893Sbrandon.potter@amd.com# 1. Redistributions of source code must retain the above copyright notice, 1212893Sbrandon.potter@amd.com# this list of conditions and the following disclaimer. 1312893Sbrandon.potter@amd.com# 1412893Sbrandon.potter@amd.com# 2. Redistributions in binary form must reproduce the above copyright notice, 1512893Sbrandon.potter@amd.com# this list of conditions and the following disclaimer in the documentation 1612893Sbrandon.potter@amd.com# and/or other materials provided with the distribution. 1712893Sbrandon.potter@amd.com# 1812893Sbrandon.potter@amd.com# 3. Neither the name of the copyright holder nor the names of its contributors 1912893Sbrandon.potter@amd.com# may be used to endorse or promote products derived from this software 2012893Sbrandon.potter@amd.com# without specific prior written permission. 2112893Sbrandon.potter@amd.com# 2212893Sbrandon.potter@amd.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2312893Sbrandon.potter@amd.com# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2412893Sbrandon.potter@amd.com# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2512893Sbrandon.potter@amd.com# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 2612893Sbrandon.potter@amd.com# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2712893Sbrandon.potter@amd.com# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2812893Sbrandon.potter@amd.com# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2912893Sbrandon.potter@amd.com# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3012893Sbrandon.potter@amd.com# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3112893Sbrandon.potter@amd.com# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3212893Sbrandon.potter@amd.com# POSSIBILITY OF SUCH DAMAGE. 3312893Sbrandon.potter@amd.com# 3412893Sbrandon.potter@amd.com# Author: Brandon Potter 3512893Sbrandon.potter@amd.com 3612893Sbrandon.potter@amd.com 3712893Sbrandon.potter@amd.comimport subprocess 3812893Sbrandon.potter@amd.comfrom collections import OrderedDict, defaultdict 3912893Sbrandon.potter@amd.com 4012893Sbrandon.potter@amd.comclass OrderedDefaultDict(OrderedDict, defaultdict): 4112893Sbrandon.potter@amd.com def __init__(self, default_factory=None, *args, **kwargs): 4212893Sbrandon.potter@amd.com super(OrderedDefaultDict, self).__init__(*args, **kwargs) 4312893Sbrandon.potter@amd.com self.default_factory = default_factory 4412893Sbrandon.potter@amd.com 4512893Sbrandon.potter@amd.comdef diff_files(upstream, feature, paths=[]): 4612893Sbrandon.potter@amd.com """Given two git branches and an optional parameter 'path', determine 4712893Sbrandon.potter@amd.com which files differ between the two branches. Afterwards, organize the 4812893Sbrandon.potter@amd.com files with a printer-friendly data structure. 4912893Sbrandon.potter@amd.com 5012893Sbrandon.potter@amd.com Returns: Dictionary of directories with their corresponding files 5112893Sbrandon.potter@amd.com """ 5212893Sbrandon.potter@amd.com 5312893Sbrandon.potter@amd.com raw = subprocess.check_output( 5412893Sbrandon.potter@amd.com [ "git", "diff", "--name-status", "%s..%s" % (upstream, feature), 5512893Sbrandon.potter@amd.com "--" ] + paths 5612893Sbrandon.potter@amd.com ) 5712893Sbrandon.potter@amd.com 5812893Sbrandon.potter@amd.com path = [line.split('\t')[1] for line in raw.splitlines()] 5912893Sbrandon.potter@amd.com 6012893Sbrandon.potter@amd.com odd = OrderedDefaultDict(list) 6112893Sbrandon.potter@amd.com for p in path: 6212893Sbrandon.potter@amd.com direc = subprocess.check_output(["dirname", p]).strip() + "/" 6312893Sbrandon.potter@amd.com filename = subprocess.check_output(["basename", p]).strip() 6412893Sbrandon.potter@amd.com odd[direc].append("%s" % filename) 6512893Sbrandon.potter@amd.com 6612893Sbrandon.potter@amd.com return odd 6712893Sbrandon.potter@amd.com 6812893Sbrandon.potter@amd.comdef cl_hash(upstream, feature, path): 6912893Sbrandon.potter@amd.com """Given two git branches and full path, record the identifier hash 7012893Sbrandon.potter@amd.com for changesets which diff between the upstream branch and feature branch. 7112893Sbrandon.potter@amd.com The changesets are ordered from oldest to youngest changesets in the 7212893Sbrandon.potter@amd.com list. 7312893Sbrandon.potter@amd.com 7412893Sbrandon.potter@amd.com Returns: List of identifier hashes 7512893Sbrandon.potter@amd.com """ 7612893Sbrandon.potter@amd.com 7712893Sbrandon.potter@amd.com raw = subprocess.check_output( 7812893Sbrandon.potter@amd.com [ "git", "log", "--oneline", "%s..%s" % (upstream, feature), 7912893Sbrandon.potter@amd.com "--", path ] 8012893Sbrandon.potter@amd.com ) 8112893Sbrandon.potter@amd.com 8212893Sbrandon.potter@amd.com return [l.split()[0] for l in raw.splitlines()] 8312893Sbrandon.potter@amd.com 8412893Sbrandon.potter@amd.comdef _main(): 8512893Sbrandon.potter@amd.com import argparse 8612893Sbrandon.potter@amd.com parser = argparse.ArgumentParser( 8712893Sbrandon.potter@amd.com description="List all changes between an upstream branch and a " \ 8812893Sbrandon.potter@amd.com "feature branch by filename(s) and changeset hash(es).") 8912893Sbrandon.potter@amd.com 9012893Sbrandon.potter@amd.com parser.add_argument("--upstream", "-u", type=str, default="origin/master", 9112893Sbrandon.potter@amd.com help="Upstream branch for comparison. " \ 9212893Sbrandon.potter@amd.com "Default: %(default)s") 9312893Sbrandon.potter@amd.com parser.add_argument("--feature", "-f", type=str, default="HEAD", 9412893Sbrandon.potter@amd.com help="Feature branch for comparison. " \ 9512893Sbrandon.potter@amd.com "Default: %(default)s") 9612893Sbrandon.potter@amd.com parser.add_argument("paths", metavar="PATH", type=str, nargs="*", 9712893Sbrandon.potter@amd.com help="Paths to list changes for") 9812893Sbrandon.potter@amd.com 9912893Sbrandon.potter@amd.com args = parser.parse_args() 10012893Sbrandon.potter@amd.com 10112893Sbrandon.potter@amd.com odd = diff_files(args.upstream, args.feature, paths=args.paths) 10212893Sbrandon.potter@amd.com 10312893Sbrandon.potter@amd.com for key, value in odd.iteritems(): 10412893Sbrandon.potter@amd.com print key 10512893Sbrandon.potter@amd.com for entry in value: 10612893Sbrandon.potter@amd.com print " %s" % entry 10712893Sbrandon.potter@amd.com path = key + entry 10812893Sbrandon.potter@amd.com sha = cl_hash(args.upstream, args.feature, path) 10912893Sbrandon.potter@amd.com for s in sha: 11012893Sbrandon.potter@amd.com print "\t%s" % s 11112893Sbrandon.potter@amd.com print 11212893Sbrandon.potter@amd.com 11312893Sbrandon.potter@amd.comif __name__ == "__main__": 11412893Sbrandon.potter@amd.com _main() 115