Skip to content

Commit 2fa0d4b

Browse files
miss-islingtonZackerySpytzgpolopriyapappachanserhiy-storchaka
authored
[3.13] gh-50948: IDLE: Warn if saving a file will overwrite a newer version (GH-17578) (GH-151028)
(cherry picked from commit 69851a6) Co-authored-by: Zackery Spytz <zspytz@gmail.com> Co-authored-by: Guilherme Polo <ggpolo@gmail.com> Co-authored-by: Priya Pappachan <priyapappachan010@gmail.com> Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent 8a69d89 commit 2fa0d4b

2 files changed

Lines changed: 28 additions & 0 deletions

File tree

Lib/idlelib/iomenu.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ def set_filename_change_hook(self, hook):
6161
self.filename_change_hook = hook
6262

6363
filename = None
64+
file_timestamp = None
6465
dirname = None
6566

6667
def set_filename(self, filename):
@@ -127,6 +128,7 @@ def loadfile(self, filename):
127128
chars = f.read()
128129
fileencoding = f.encoding
129130
eol_convention = f.newlines
131+
file_timestamp = self.getmtime(filename)
130132
converted = False
131133
except (UnicodeDecodeError, SyntaxError):
132134
# Wait for the editor window to appear
@@ -142,6 +144,7 @@ def loadfile(self, filename):
142144
chars = f.read()
143145
fileencoding = f.encoding
144146
eol_convention = f.newlines
147+
file_timestamp = self.getmtime(filename)
145148
converted = True
146149
except OSError as err:
147150
messagebox.showerror("I/O Error", str(err), parent=self.text)
@@ -170,6 +173,7 @@ def loadfile(self, filename):
170173
self.text.insert("1.0", chars)
171174
self.reset_undo()
172175
self.set_filename(filename)
176+
self.file_timestamp = file_timestamp
173177
if converted:
174178
# We need to save the conversion results first
175179
# before being able to execute the code
@@ -206,7 +210,26 @@ def save(self, event):
206210
if not self.filename:
207211
self.save_as(event)
208212
else:
213+
# Check the time of most recent content modification so the
214+
# user doesn't accidentally overwrite a newer version of the file.
215+
try:
216+
file_timestamp = self.getmtime(self.filename)
217+
except OSError:
218+
pass
219+
else:
220+
if self.file_timestamp != file_timestamp:
221+
confirm = messagebox.askokcancel(
222+
title="File has changed",
223+
message=(
224+
"The file has changed on disk since reading it!\n\n"
225+
"Do you really want to overwrite it?"),
226+
default=messagebox.CANCEL,
227+
parent=self.text)
228+
if not confirm:
229+
return "break"
230+
209231
if self.writefile(self.filename):
232+
self.file_timestamp = self.getmtime(self.filename)
210233
self.set_saved(True)
211234
try:
212235
self.editwin.store_file_breaks()
@@ -219,6 +242,7 @@ def save_as(self, event):
219242
filename = self.asksavefile()
220243
if filename:
221244
if self.writefile(filename):
245+
self.file_timestamp = self.getmtime(filename)
222246
self.set_filename(filename)
223247
self.set_saved(1)
224248
try:
@@ -251,6 +275,9 @@ def writefile(self, filename):
251275
parent=self.text)
252276
return False
253277

278+
def getmtime(self, filename):
279+
return os.stat(filename).st_mtime
280+
254281
def fixnewlines(self):
255282
"""Return text with os eols.
256283
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Warn the user if a file will be overwritten when saving.

0 commit comments

Comments
 (0)