Merge pull request #15596 from CarolEidt/RemoveMap
[platform/upstream/coreclr.git] / src / scripts / utilities.py
1 ##
2 ## Licensed to the .NET Foundation under one or more agreements.
3 ## The .NET Foundation licenses this file to you under the MIT license.
4 ## See the LICENSE file in the project root for more information.
5 ##
6 ##  This file provides utility functions to the adjacent python scripts
7
8 from filecmp import dircmp
9 from hashlib import sha256
10 from io import StringIO
11 import shutil
12 import sys
13 import os
14
15 class WrappedStringIO(StringIO):
16     """A wrapper around StringIO to allow writing str objects"""
17     def write(self, s):
18         if sys.version_info < (3, 0, 0):
19             if isinstance(s, str):
20                 s = unicode(s)
21         super(WrappedStringIO, self).write(s)
22
23 class UpdateFileWriter:
24     """A file-like context object which will only write to a file if the result would be different
25
26     Attributes:
27         filename (str): The name of the file to update
28         stream (WrappedStringIO): The file-like stream provided upon context enter
29
30     Args:
31         filename (str): Sets the filename attribute
32     """
33     filemode = 'w'
34
35     def __init__(self, filename):
36         self.filename = filename
37         self.stream = None
38
39     def __enter__(self):
40         self.stream = WrappedStringIO()
41         return self.stream
42
43     def __exit__(self, exc_type, exc_value, traceback):
44         if exc_value is None:
45             new_content = self.stream.getvalue()
46             new_hash = sha256()
47             cur_hash = sha256()
48
49             try:
50                 with open(self.filename, 'r') as fstream:
51                     cur_hash.update(fstream.read().encode('utf-8'))
52                 file_found = True
53             except IOError:
54                 file_found = False
55
56             if file_found:
57                 new_hash.update(new_content.encode('utf-8'))
58                 update = new_hash.digest() != cur_hash.digest()
59             else:
60                 update = True
61
62             if update:
63                 with open(self.filename, 'w') as fstream:
64                     fstream.write(new_content)
65
66         self.stream.close()
67
68 def open_for_update(filename):
69     return UpdateFileWriter(filename)
70
71 def walk_recursively_and_update(dcmp):
72     #for different Files Copy from right to left
73     for name in dcmp.diff_files:
74         srcpath = dcmp.right + "/" + name
75         destpath = dcmp.left + "/" + name
76         print("Updating %s" % (destpath))
77         if  os.path.isfile(srcpath):
78             shutil.copyfile(srcpath, destpath)
79         else :
80             raise Exception("path: " + srcpath + "is neither a file or folder")
81
82     #copy right only files
83     for name in dcmp.right_only:
84         srcpath = dcmp.right + "/" + name
85         destpath = dcmp.left + "/" + name
86         print("Updating %s" % (destpath))
87         if  os.path.isfile(srcpath):
88             shutil.copyfile(srcpath, destpath)
89         elif  os.path.isdir(srcpath):
90             shutil.copytree(srcpath, destpath)
91         else :
92             raise Exception("path: " + srcpath + "is neither a file or folder")
93
94     #delete left only files
95     for name in dcmp.left_only:
96         path = dcmp.left + "/" + name
97         print("Deleting %s" % (path))
98         if  os.path.isfile(path):
99             os.remove(path)
100         elif  os.path.isdir(path):
101             shutil.rmtree(path)
102         else :
103             raise Exception("path: " + path + "is neither a file or folder")
104
105     #call recursively
106     for sub_dcmp in dcmp.subdirs.values():
107         walk_recursively_and_update(sub_dcmp)
108
109 def UpdateDirectory(destpath,srcpath):
110
111     print("Updating %s with %s" % (destpath,srcpath))
112     if not os.path.exists(destpath):
113         os.makedirs(destpath)
114     dcmp = dircmp(destpath,srcpath)
115     walk_recursively_and_update(dcmp)