Author Topic: When saving a file after modifications, preserve creation date timestamp  (Read 4013 times)

Offline Butter-Swimming Butterfly

  • Multiple posting newcomer
  • *
  • Posts: 15
After I save a file I've just modified using Code::Blocks 16.01 or Nightly Build Nov 20, 2016 17:01:59 (on Windows), the file's creation date property is reset. Original creation dates can be extremely useful for reviewing progress!

----

When a document being used to overwrite another was opened using the same path as where it's writing upon (i.e. Not overwriting a file using 'Save file as...'), the creation date should not be reset.

----

I decided to have a look at Code::Block's source for my first time (I'm a noob). This looks like the first routine which needs to be changed to begin resolving the issue:

src\sdk\filemanager.cpp, FileManager::Save()
Code
bool FileManager::Save(const wxString& name, const wxString& data, wxFontEncoding encoding, bool bom)
{
    if (wxFileExists(name) == false)
    {
        wxFile f(name, wxFile::write_excl);
        return WriteWxStringToFile(f, data, encoding, bom);
    }
#if wxCHECK_VERSION(3, 0, 0)
    else if (wxFileName::Exists(name, wxFILE_EXISTS_SYMLINK))
    {
        // Enable editing symlinks. Do not use temp file->replace procedure
        // since that would get rid of the symlink. Writing directly causes
        // edits to reflect to the target file.
        wxFile f(name, wxFile::write);
        return WriteWxStringToFile(f, data, encoding, bom);
    }
#endif // wxCHECK_VERSION(3, 0, 0)
    else
    {
        if (!wxFile::Access(name, wxFile::write))
            return false;

        wxString temp(name);
        temp.append(wxT(".temp"));

        wxStructStat buff;
        wxLstat( name, &buff );

        wxFile f;
        f.Create(temp, true, buff.st_mode);

        if (WriteWxStringToFile(f, data, encoding, bom))
        {
            f.Close();
            if (platform::move(temp, name))
            {
                return true;
            }
            else
            {
                wxString failed(name);
                failed.append(wxT(".save-failed"));
                platform::move(temp, failed);
            }
        }
        return false;
    }
}

If the filename parameter does already exist, there's a branch (referred to within a comment as the "temp file->replace procedure"?) which first writes the file data to a temporary file, and apparently renames this file to use the intended filename. This means the intended file will completely inherit the temporary file's properties.

Just to pretend to be robust, if the "platform::move(temp, name)" call fails, then it instead names temp as name with an appended *.save-failed extension. It looks like there's already a condition to verify write access (upon name) before proceeding.
Code
        if (!wxFile::Access(name, wxFile::write))
            return false;

So here's my question: Why not inverse this "temp file->replace procedure" into a temporary backup procedure?

Copy the existing file's contents to a temporary file (like name + ".backup").
If the copy is made successfully, write to the existing file identified as name with data
If the write succeeds, delete the temporary *.backup file.
« Last Edit: March 10, 2017, 05:23:03 am by Eyeball Veins »

Offline sodev

  • Regular
  • ***
  • Posts: 497
Well, uhm, maybe 15 years ago that might have been a small issue, but what importance does have the creation date of a local file today? Use a revision control system (svn, git, whatever) to track your changes, you get persistent and consistent timestamps even across multiple systems for free.

Offline Butter-Swimming Butterfly

  • Multiple posting newcomer
  • *
  • Posts: 15
I experimented with that for a while.

uhm

It's an answer which makes sense in some situations, but it is not a definite answer for Code::Blocks.
« Last Edit: March 10, 2017, 05:44:51 am by Eyeball Veins »

Online Commaster

  • Almost regular
  • **
  • Posts: 171
Copy the existing file's contents to a temporary file (like name + ".backup").
If the copy is made successfully, write to the existing file identified as name with data
If the write succeeds, delete the temporary *.backup file.
Okay, let's see. We successfully make a backup, start overwriting the original file ... and suddenly the power drops. So... What do we do now? Is the original file ok? It's still "a file" and has text in it...

Offline Butter-Swimming Butterfly

  • Multiple posting newcomer
  • *
  • Posts: 15
Maybe rename the original as *.write-queued and don't rename it back as the intended filename until the file handle is closed and disk operation is complete, granted the Rename() call used works as expected.

Another thought: suppose failure at any point discussed above (including if (!wxFile::Access(name, wxFile::write)), i.e. almost any return false;. Then at least the routine may try to output a *.save-failed file just to hope the modified changes are not lost (no renaming involved). I guess I'm saying "pretending to be robust" may at least be a little better than doing otherwise. :)
« Last Edit: March 10, 2017, 06:32:09 pm by Eyeball Veins »