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.
6 ## This file provides utility functions to the adjacent python scripts
8 from filecmp import dircmp
9 from hashlib import sha256
10 from io import StringIO
15 class WrappedStringIO(StringIO):
16 """A wrapper around StringIO to allow writing str objects"""
18 if sys.version_info < (3, 0, 0):
19 if isinstance(s, str):
21 super(WrappedStringIO, self).write(s)
23 class UpdateFileWriter:
24 """A file-like context object which will only write to a file if the result would be different
27 filename (str): The name of the file to update
28 stream (WrappedStringIO): The file-like stream provided upon context enter
31 filename (str): Sets the filename attribute
35 def __init__(self, filename):
36 self.filename = filename
40 self.stream = WrappedStringIO()
43 def __exit__(self, exc_type, exc_value, traceback):
45 new_content = self.stream.getvalue()
50 with open(self.filename, 'r') as fstream:
51 cur_hash.update(fstream.read().encode('utf-8'))
57 new_hash.update(new_content.encode('utf-8'))
58 update = new_hash.digest() != cur_hash.digest()
63 with open(self.filename, 'w') as fstream:
64 fstream.write(new_content)
68 def open_for_update(filename):
69 return UpdateFileWriter(filename)
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)
80 raise Exception("path: " + srcpath + "is neither a file or folder")
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)
92 raise Exception("path: " + srcpath + "is neither a file or folder")
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):
100 elif os.path.isdir(path):
103 raise Exception("path: " + path + "is neither a file or folder")
106 for sub_dcmp in dcmp.subdirs.values():
107 walk_recursively_and_update(sub_dcmp)
109 def UpdateDirectory(destpath,srcpath):
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)