Skip to content

Commit b81af70

Browse files
Simplify create file and folder placeholder (#201)
1 parent f626ddb commit b81af70

12 files changed

Lines changed: 105 additions & 311 deletions

File tree

.github/workflows/publish.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
types: [published]
66

77
jobs:
8-
publish_npm:
8+
publish:
99
runs-on: ubuntu-latest
1010
timeout-minutes: 1
1111

@@ -24,7 +24,7 @@ jobs:
2424
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2525
run: |
2626
echo "@internxt:registry=https://npm.pkg.github.com/" > .npmrc
27-
echo "//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN >> .npmrc
27+
echo "//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN" >> .npmrc
2828
2929
- name: Publish package to github
3030
run: npm publish --scope=@internxt --access public

dist/addon.node

-12 KB
Binary file not shown.

include/placeholders_interface/Placeholders.h

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,13 @@
33
#include <string>
44
#include <PlaceholderInfo.h>
55

6-
struct PlaceholderResult {
7-
bool success;
8-
std::wstring errorMessage;
9-
};
10-
116
class Placeholders
127
{
138
public:
14-
static PlaceholderResult CreateOne(
15-
const wchar_t *fileName,
16-
const wchar_t *fileIdentity,
17-
int64_t fileSize,
18-
LARGE_INTEGER creationTime,
19-
LARGE_INTEGER lastWriteTime,
20-
LARGE_INTEGER lastAccessTime,
21-
const wchar_t *destPath);
22-
239
static void MaintainIdentity(std::wstring &fullPath, PCWSTR fileIdentity, bool isDirectory);
24-
25-
static PlaceholderResult CreateEntry(
26-
const wchar_t *itemName,
27-
const wchar_t *itemIdentity,
28-
LARGE_INTEGER creationTime,
29-
LARGE_INTEGER lastWriteTime,
30-
LARGE_INTEGER lastAccessTime,
31-
const wchar_t *destPath);
32-
3310
static void ForceShellRefresh(const std::wstring &path);
3411
static void UpdateSyncStatus(const std::wstring &filePath, bool syncState, bool isDirectory);
3512
static HRESULT UpdatePinState(const std::wstring &path, const PinState state);
36-
static PlaceholderResult ConvertToPlaceholder(const std::wstring &fullPath, const std::wstring &serverIdentity);
3713
static std::string GetFileIdentity(const std::wstring &filePath);
3814
static void UpdateFileIdentity(const std::wstring &filePath, const std::wstring &fileIdentity, bool isDirectory);
3915
static FileState GetPlaceholderInfo(const std::wstring &directoryPath);

include/virtual_drive/Wrappers.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
#include <node_api.h>
44

5-
napi_value CreatePlaceholderFile(napi_env env, napi_callback_info args);
5+
napi_value CreateFilePlaceholderWrapper(napi_env env, napi_callback_info args);
6+
napi_value CreateFolderPlaceholderWrapper(napi_env env, napi_callback_info args);
67
napi_value UnregisterSyncRootWrapper(napi_env env, napi_callback_info args);
78
napi_value RegisterSyncRootWrapper(napi_env env, napi_callback_info args);
89
napi_value GetRegisteredSyncRootsWrapper(napi_env env, napi_callback_info args);
910
napi_value ConnectSyncRootWrapper(napi_env env, napi_callback_info args);
10-
napi_value CreateEntryWrapper(napi_env env, napi_callback_info args);
1111
napi_value DisconnectSyncRootWrapper(napi_env env, napi_callback_info args);
1212
napi_value GetFileIdentityWrapper(napi_env env, napi_callback_info args);
1313
napi_value addLoggerPathWrapper(napi_env env, napi_callback_info args);

include/virtual_drive/convert_to_placeholder.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22

33
#include <node_api.h>
44

5-
napi_value convert_to_placeholder_impl(napi_env env, napi_callback_info args);
5+
napi_value convert_to_placeholder_wrapper(napi_env env, napi_callback_info args);
6+
void convert_to_placeholder(const std::wstring &path, const std::wstring &placeholderId);

native-src/main.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
napi_value init(napi_env env, napi_value exports)
55
{
66
napi_property_descriptor desc = {
7-
"createPlaceholderFile",
7+
"createFilePlaceholder",
88
nullptr,
9-
CreatePlaceholderFile,
9+
CreateFilePlaceholderWrapper,
1010
nullptr,
1111
nullptr,
1212
nullptr,
@@ -88,20 +88,20 @@ napi_value init(napi_env env, napi_value exports)
8888
return nullptr;
8989
}
9090

91-
napi_property_descriptor createEntryDesc = {
92-
"createEntry",
91+
napi_property_descriptor createFolderPlaceholderDesc = {
92+
"createFolderPlaceholder",
9393
nullptr,
94-
CreateEntryWrapper,
94+
CreateFolderPlaceholderWrapper,
9595
nullptr,
9696
nullptr,
9797
nullptr,
9898
napi_default,
9999
nullptr};
100100

101-
napi_status defineCreateEntryStatus = napi_define_properties(env, exports, 1, &createEntryDesc);
102-
if (defineCreateEntryStatus != napi_ok)
101+
napi_status defineCreateFolderPlaceholderStatus = napi_define_properties(env, exports, 1, &createFolderPlaceholderDesc);
102+
if (defineCreateFolderPlaceholderStatus != napi_ok)
103103
{
104-
napi_throw_error(env, nullptr, "Failed to define createEntry function");
104+
napi_throw_error(env, nullptr, "Failed to define createFolderPlaceholder function");
105105
return nullptr;
106106
}
107107

native-src/placeholders_interface/Planceholders.cpp

Lines changed: 2 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -15,88 +15,14 @@
1515
#include <cctype>
1616
#include <windows.h>
1717
#include <shlobj.h>
18+
#include "convert_to_placeholder.h"
1819

1920
using namespace std;
2021

2122
namespace fs = std::filesystem;
2223

2324
#pragma comment(lib, "shlwapi.lib")
2425

25-
bool DirectoryExists(const wchar_t *path)
26-
{
27-
DWORD attributes = GetFileAttributesW(path);
28-
return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY);
29-
}
30-
31-
PlaceholderResult Placeholders::CreateOne(
32-
const wchar_t *fileName,
33-
const wchar_t *fileIdentity,
34-
int64_t fileSize,
35-
LARGE_INTEGER creationTime,
36-
LARGE_INTEGER lastWriteTime,
37-
LARGE_INTEGER lastAccessTime,
38-
const wchar_t *destPath)
39-
{
40-
PlaceholderResult result = {false, L""};
41-
42-
try
43-
{
44-
CF_PLACEHOLDER_CREATE_INFO cloudEntry = {};
45-
46-
std::wstring fullDestPath = std::wstring(destPath) + L'\\';
47-
48-
wstring fullPath = std::wstring(destPath) + L'\\' + fileName;
49-
50-
if (std::filesystem::exists(fullPath))
51-
{
52-
Placeholders::ConvertToPlaceholder(fullPath, fileIdentity);
53-
Placeholders::MaintainIdentity(fullPath, fileIdentity, false);
54-
result.success = true;
55-
return result;
56-
}
57-
58-
std::wstring relativeName(fileIdentity);
59-
60-
cloudEntry.FileIdentity = relativeName.c_str();
61-
cloudEntry.FileIdentityLength = static_cast<DWORD>((relativeName.size() + 1) * sizeof(WCHAR));
62-
63-
cloudEntry.RelativeFileName = fileName;
64-
cloudEntry.Flags = CF_PLACEHOLDER_CREATE_FLAG_MARK_IN_SYNC;
65-
66-
cloudEntry.FsMetadata.FileSize.QuadPart = fileSize;
67-
cloudEntry.FsMetadata.BasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
68-
cloudEntry.FsMetadata.BasicInfo.CreationTime = creationTime;
69-
cloudEntry.FsMetadata.BasicInfo.LastWriteTime = lastWriteTime;
70-
cloudEntry.FsMetadata.BasicInfo.LastAccessTime = lastAccessTime;
71-
cloudEntry.FsMetadata.BasicInfo.ChangeTime = lastWriteTime;
72-
73-
try
74-
{
75-
winrt::check_hresult(CfCreatePlaceholders(fullDestPath.c_str(), &cloudEntry, 1, CF_CREATE_FLAG_NONE, NULL));
76-
Placeholders::UpdatePinState(fullPath, PinState::OnlineOnly);
77-
result.success = true;
78-
}
79-
catch (const winrt::hresult_error &error)
80-
{
81-
result.errorMessage = error.message().c_str();
82-
wprintf(L"[CreatePlaceholder] error: %s", error.message().c_str());
83-
}
84-
winrt::StorageProviderItemProperty prop;
85-
prop.Id(1);
86-
prop.Value(L"Value1");
87-
prop.IconResource(L"shell32.dll,-44");
88-
89-
// UpdateSyncStatus(fullDestPath, true, false);
90-
}
91-
catch (...)
92-
{
93-
result.errorMessage = L"Failed to create or customize placeholder";
94-
wprintf(L"[CreatePlaceholder] Failed to create or customize placeholder with %08x\n", static_cast<HRESULT>(winrt::to_hresult()));
95-
}
96-
97-
return result;
98-
}
99-
10026
std::string cleanString(const std::string &str)
10127
{
10228
std::string cleanedStr;
@@ -136,133 +62,6 @@ void Placeholders::MaintainIdentity(std::wstring &fullPath, PCWSTR itemIdentity,
13662
}
13763
}
13864

139-
PlaceholderResult Placeholders::CreateEntry(
140-
const wchar_t *itemName,
141-
const wchar_t *itemIdentity,
142-
LARGE_INTEGER creationTime,
143-
LARGE_INTEGER lastWriteTime,
144-
LARGE_INTEGER lastAccessTime,
145-
const wchar_t *destPath)
146-
{
147-
PlaceholderResult result = {false, L""};
148-
149-
std::wstring fullDestPath = std::wstring(destPath) + L"\\" + std::wstring(itemName);
150-
CF_PLACEHOLDER_CREATE_INFO cloudEntry = {};
151-
std::wstring relativeName(itemIdentity);
152-
cloudEntry.FileIdentity = relativeName.c_str();
153-
cloudEntry.FileIdentityLength = static_cast<DWORD>((relativeName.size() + 1) * sizeof(WCHAR));
154-
cloudEntry.RelativeFileName = itemName;
155-
cloudEntry.Flags = CF_PLACEHOLDER_CREATE_FLAG_DISABLE_ON_DEMAND_POPULATION; // -> desactive download on demand
156-
cloudEntry.FsMetadata.BasicInfo.FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
157-
cloudEntry.FsMetadata.BasicInfo.CreationTime = creationTime;
158-
cloudEntry.FsMetadata.BasicInfo.LastWriteTime = lastWriteTime;
159-
cloudEntry.FsMetadata.BasicInfo.LastAccessTime = lastAccessTime;
160-
161-
try
162-
{
163-
// TODO: si existe o es placeholder return
164-
if (DirectoryExists(fullDestPath.c_str()))
165-
{
166-
Placeholders::ConvertToPlaceholder(fullDestPath, itemIdentity);
167-
Placeholders::MaintainIdentity(fullDestPath, itemIdentity, true);
168-
result.success = true;
169-
return result;
170-
}
171-
172-
// wprintf(L"Create directory, full destination path: %ls, fullDestPath.c_str()");
173-
PathRemoveFileSpecW(&fullDestPath[0]);
174-
HRESULT hr = CfCreatePlaceholders(fullDestPath.c_str(), &cloudEntry, 1, CF_CREATE_FLAG_NONE, NULL);
175-
if (FAILED(hr))
176-
{
177-
result.errorMessage = L"Failed to create placeholder directory";
178-
wprintf(L"[CreatePlaceholder] Failed to create placeholder directory with HRESULT 0x%08x\n", hr);
179-
throw winrt::hresult_error(hr);
180-
}
181-
182-
std::wstring finalPath = std::wstring(destPath) + L"\\" + std::wstring(itemName);
183-
Placeholders::UpdatePinState(finalPath, PinState::OnlineOnly);
184-
UpdateSyncStatus(finalPath, true, true);
185-
result.success = true;
186-
}
187-
catch (const winrt::hresult_error &error)
188-
{
189-
result.errorMessage = error.message().c_str();
190-
wprintf(L"[CreatePlaceholder] Error while creating %s: %s\n", L"directory", error.message().c_str());
191-
}
192-
catch (...)
193-
{
194-
result.errorMessage = L"Unknown error occurred";
195-
wprintf(L"[CreatePlaceholder] Unknown error occurred\n");
196-
}
197-
198-
return result;
199-
}
200-
201-
PlaceholderResult Placeholders::ConvertToPlaceholder(const std::wstring &fullPath, const std::wstring &serverIdentity)
202-
{
203-
PlaceholderResult result = {false, L""};
204-
205-
if (!std::filesystem::exists(fullPath))
206-
{
207-
result.errorMessage = L"File does not exist";
208-
return result;
209-
}
210-
211-
wprintf(L"[ConvertToPlaceholder] Full path: %ls\n", fullPath.c_str());
212-
bool isDirectory = fs::is_directory(fullPath);
213-
214-
HANDLE fileHandle = CreateFileW(
215-
fullPath.c_str(),
216-
FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
217-
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
218-
nullptr,
219-
OPEN_EXISTING,
220-
isDirectory ? FILE_FLAG_BACKUP_SEMANTICS : 0,
221-
nullptr);
222-
223-
if (fileHandle == INVALID_HANDLE_VALUE)
224-
{
225-
result.errorMessage = L"Failed to open file: " + std::to_wstring(GetLastError());
226-
return result;
227-
}
228-
229-
CF_CONVERT_FLAGS convertFlags = CF_CONVERT_FLAG_MARK_IN_SYNC;
230-
USN convertUsn;
231-
OVERLAPPED overlapped = {};
232-
233-
LPCVOID idStrLPCVOID = static_cast<LPCVOID>(serverIdentity.c_str());
234-
DWORD idStrByteLength = static_cast<DWORD>(serverIdentity.size() * sizeof(wchar_t));
235-
236-
HRESULT hr = CfConvertToPlaceholder(fileHandle, idStrLPCVOID, idStrByteLength, convertFlags, &convertUsn, &overlapped);
237-
238-
if (FAILED(hr))
239-
{
240-
CloseHandle(fileHandle);
241-
if (hr != 0x8007017C) // Ignorar error específico de "ya es un placeholder"
242-
{
243-
result.errorMessage = L"Failed to convert to placeholder. HRESULT: 0x" + std::to_wstring(static_cast<unsigned int>(hr));
244-
return result;
245-
}
246-
return result;
247-
}
248-
249-
if (!isDirectory)
250-
{
251-
HRESULT hrPinState = CfSetPinState(fileHandle, CF_PIN_STATE_PINNED, CF_SET_PIN_FLAG_NONE, nullptr);
252-
if (FAILED(hrPinState))
253-
{
254-
CloseHandle(fileHandle);
255-
result.errorMessage = L"Failed to set pin state. HRESULT: 0x" + std::to_wstring(static_cast<unsigned int>(hrPinState));
256-
return result;
257-
}
258-
}
259-
260-
CloseHandle(fileHandle);
261-
wprintf(L"[ConvertToPlaceholder] Successfully converted to placeholder: %ls\n", fullPath.c_str());
262-
result.success = true;
263-
return result;
264-
}
265-
26665
/**
26766
* @brief Mark a file or directory as synchronized
26867
* @param filePath path to the file or directory
@@ -315,7 +114,7 @@ void Placeholders::UpdateSyncStatus(const std::wstring &filePath,
315114
break;
316115

317116
case ERROR_CLOUD_FILE_NOT_IN_SYNC:
318-
ConvertToPlaceholder(filePath, L"temp_identity");
117+
convert_to_placeholder(filePath, L"temp_identity");
319118
hr = CfSetInSyncState(h, sync, CF_SET_IN_SYNC_FLAG_NONE, nullptr);
320119
wprintf(L"[UpdateSyncStatus] Retry CfSetInSyncState\n");
321120
break;

native-src/virtual_drive/Wrappers.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include "update_sync_status_wrapper.h"
2424
#include "NAPI_SAFE_WRAP.h"
2525

26-
napi_value CreatePlaceholderFile(napi_env env, napi_callback_info args) {
26+
napi_value CreateFilePlaceholderWrapper(napi_env env, napi_callback_info args) {
2727
return NAPI_SAFE_WRAP(env, args, create_file_placeholder_impl);
2828
}
2929

@@ -43,7 +43,7 @@ napi_value ConnectSyncRootWrapper(napi_env env, napi_callback_info args) {
4343
return NAPI_SAFE_WRAP(env, args, connect_sync_root_impl);
4444
}
4545

46-
napi_value CreateEntryWrapper(napi_env env, napi_callback_info args) {
46+
napi_value CreateFolderPlaceholderWrapper(napi_env env, napi_callback_info args) {
4747
return NAPI_SAFE_WRAP(env, args, create_folder_placeholder_impl);
4848
}
4949

@@ -104,7 +104,7 @@ napi_value GetPlaceholderStateWrapper(napi_env env, napi_callback_info args) {
104104
}
105105

106106
napi_value ConvertToPlaceholderWrapper(napi_env env, napi_callback_info args) {
107-
return NAPI_SAFE_WRAP(env, args, convert_to_placeholder_impl);
107+
return NAPI_SAFE_WRAP(env, args, convert_to_placeholder_wrapper);
108108
}
109109

110110
napi_value HydrateFileWrapper(napi_env env, napi_callback_info args) {

0 commit comments

Comments
 (0)