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