# HG changeset patch
# User Adrian Buehlmann <[email protected]>
# Date 1244728880 -7200
# Node ID 02421951ec021aa54cdc7d465d123e3cefe6a2a9
# Parent  b325289450286a1814e3ab54adc585fa352c4e0c
shellext: allow other processes to rename files we have open

- introduce new function fopenReadRenameAllowed in TortoiseUtils.cpp
- use it to open .hg/dirstate and .hg/thgstatus

diff --git a/win32/shellext/DirectoryStatus.cpp 
b/win32/shellext/DirectoryStatus.cpp
--- a/win32/shellext/DirectoryStatus.cpp
+++ b/win32/shellext/DirectoryStatus.cpp
@@ -18,6 +18,7 @@
 
 #include "DirectoryStatus.h"
 #include "Thgstatus.h"
+#include "TortoiseUtils.h"
 
 
 char DirectoryStatus::status(const std::string& relpath_) const
@@ -61,7 +62,7 @@ int DirectoryStatus::read(const std::str
 
     std::string p = hgroot + "\\.hg\\thgstatus";
 
-    FILE *f = fopen(p.c_str(), "rb");
+    FILE *f = fopenReadRenameAllowed(p.c_str());
     if (!f)
     {
         TDEBUG_TRACE("DirectoryStatus::read: can't open '" << p << "'");
diff --git a/win32/shellext/TortoiseUtils.cpp b/win32/shellext/TortoiseUtils.cpp
--- a/win32/shellext/TortoiseUtils.cpp
+++ b/win32/shellext/TortoiseUtils.cpp
@@ -4,6 +4,10 @@
 #include "errno.h"
 #include <assert.h>
 
+#include <io.h>
+#include "FCNTL.H"
+
+
 int WideCharToLocal(LPTSTR pLocal, LPWSTR pWide, DWORD dwChars)
 {
        *pLocal = 0;
@@ -242,3 +246,36 @@ bool IsHgRepo(const std::string& path)
     return !GetHgRepoRoot(path).empty();
 }
 
+
+// open a file for reading, allowing renames and deletes by other
+// processes while we have it open
+FILE* fopenReadRenameAllowed(const char* path)
+{
+    HANDLE fh = ::CreateFileA(
+      path, GENERIC_READ,
+      FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+      0, OPEN_EXISTING, 0, 0
+    );
+
+    if (fh == INVALID_HANDLE_VALUE)
+        return 0;
+
+    // get C runtime file descriptor from file handle
+    int fd = ::_open_osfhandle ((intptr_t)fh, _O_RDONLY);
+    if (fd == -1)
+    {
+        TDEBUG_TRACE("fopenReadRenameAllowed: _open_osfhandle failed");
+        return 0;
+    }
+
+    // get C runtime FILE from file descriptor
+    FILE* f = ::_fdopen(fd, "r");
+    if (f == 0)
+    {
+        TDEBUG_TRACE("fopenReadRenameAllowed: _fdopen failed");
+        return 0;
+    }
+
+    return f;
+}
+
diff --git a/win32/shellext/TortoiseUtils.h b/win32/shellext/TortoiseUtils.h
--- a/win32/shellext/TortoiseUtils.h
+++ b/win32/shellext/TortoiseUtils.h
@@ -38,5 +38,6 @@ HICON GetTortoiseIcon(const std::string 
 std::string GetHgRepoRoot(const std::string& path);
 bool IsHgRepo(const std::string& path);
 int GetRegistryConfig(const std::string& name, std::string& res);
+FILE* fopenReadRenameAllowed(const char* path);
 
 #endif
diff --git a/win32/shellext/dirstate.cpp b/win32/shellext/dirstate.cpp
--- a/win32/shellext/dirstate.cpp
+++ b/win32/shellext/dirstate.cpp
@@ -18,13 +18,14 @@
 #include "stdafx.h"
 
 #include "dirstate.h"
+#include "TortoiseUtils.h"
 
 
 std::auto_ptr<Dirstate> Dirstate::read(const std::string& path, bool& unset)
 {
     unset = false;
 
-    FILE *f = fopen(path.c_str(), "rb");
+    FILE *f = fopenReadRenameAllowed(path.c_str());
     if (!f)
     {
         TDEBUG_TRACE("Dirstate::read: can't open " << path);

------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables unlimited
royalty-free distribution of the report engine for externally facing 
server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
Tortoisehg-develop mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tortoisehg-develop

Reply via email to