diff --git a/.github/workflows/macos-build-and-test.yml b/.github/workflows/macos-build-and-test.yml new file mode 100644 index 0000000000000..a1bbe8d25b882 --- /dev/null +++ b/.github/workflows/macos-build-and-test.yml @@ -0,0 +1,60 @@ +name: macOS Build and Test +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + name: Build + runs-on: macos-latest + env: + CRAFT_TARGET: macos-64-clang + CRAFT_MASTER_LOCATION: ${{ github.workspace }}/CraftMaster + CRAFT_MASTER_CONFIG: ${{ github.workspace }}/craftmaster.ini + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 1 + + - name: Restore cache + uses: actions/cache@v2 + with: + path: ~/cache + key: macos-latest-${{ env.CRAFT_TARGET }} + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: 3.9 + + - name: Install Homebrew dependencies + run: | + brew install inkscape + + - name: Download Craft + run: | + git clone -q --depth=1 https://invent.kde.org/packaging/craftmaster.git ${{ env.CRAFT_MASTER_LOCATION }} + + - name: Add Nextcloud client blueprints + run: | + python "${{ env.CRAFT_MASTER_LOCATION }}/CraftMaster.py" --config "${{ env.CRAFT_MASTER_CONFIG }}" --target ${{ env.CRAFT_TARGET }} -c --add-blueprint-repository https://github.com/nextcloud/desktop-client-blueprints.git + + - name: Setup Craft + run: | + python "${{ env.CRAFT_MASTER_LOCATION }}/CraftMaster.py" --config "${{ env.CRAFT_MASTER_CONFIG }}" --target ${{ env.CRAFT_TARGET }} -c craft + + - name: Install Craft Nextcloud client dependencies + run: | + python "${{ env.CRAFT_MASTER_LOCATION }}/CraftMaster.py" --config "${{ env.CRAFT_MASTER_CONFIG }}" --target ${{ env.CRAFT_TARGET }} -c --install-deps nextcloud-client + + - name: Build client + run: | + python "${{ env.CRAFT_MASTER_LOCATION }}/CraftMaster.py" --config "${{ env.CRAFT_MASTER_CONFIG }}" --target ${{ env.CRAFT_TARGET }} -c --src-dir ${{ github.workspace }} nextcloud-client + + - name: Run tests + run: | + cd ${{ github.workspace }}/${{ env.CRAFT_TARGET }}/build/nextcloud-client/work/build + ctest --output-on-failure --output-junit testResult.xml + diff --git a/craftmaster.ini b/craftmaster.ini index da7d7f5c902fc..095286a8686fa 100644 --- a/craftmaster.ini +++ b/craftmaster.ini @@ -15,6 +15,8 @@ CreateCache = False # Category is case sensitive [GeneralSettings] +General/MacDeploymentTarget = 10.15 + ## This is the location of your python installation. ## This value must be set. Paths/Python = C:\Python39-x64 @@ -42,6 +44,13 @@ Packager/UseCache = ${Variables:UseCache} Packager/CreateCache = ${Variables:CreateCache} Packager/CacheDir = ${Variables:Root}\cache +#CodeSigning/Enabled = ${Env:SIGN_PACKAGE} +#CodeSigning/Protected = True +#CodeSigning/Certificate = ${Env:CRAFT_CODESIGN_CERTIFICATE} +#CodeSigning/CommonName = +#CodeSigning/MacDeveloperId = ownCloud GmbH (4AP2STM4H5) +#CodeSigning/MacKeychainPath = sign-${Env:DRONE_BUILD_NUMBER}.keychain + [BlueprintSettings] # don't try to pip install on the ci python-modules.ignored = True @@ -53,3 +62,22 @@ binary/mysql.useMariaDB = False [windows-msvc2019_64-cl] QtSDK/Compiler = msvc2019_64 General/ABI = windows-msvc2019_64-cl + +[macos-64-clang] +General/ABI = macos-64-clang +# Packager/PackageType = MacPkgPackager + +[macos-64-clang-debug] +General/ABI = macos-64-clang +Compile/BuildType = Debug + +[macos-clang-arm64] +General/ABI = macos-clang-arm64 + +[macos-clang-arm64-debug] +General/ABI = macos-clang-arm64 +Compile/BuildType = Debug + +[Env] +CRAFT_CODESIGN_CERTIFICATE = +SIGN_PACKAGE = False \ No newline at end of file diff --git a/src/gui/folderwatcher_mac.cpp b/src/gui/folderwatcher_mac.cpp index fcce031cdaf66..588b94a27b561 100644 --- a/src/gui/folderwatcher_mac.cpp +++ b/src/gui/folderwatcher_mac.cpp @@ -48,18 +48,32 @@ static void callback( const FSEventStreamEventId eventIds[]) { Q_UNUSED(streamRef) - Q_UNUSED(eventFlags) Q_UNUSED(eventIds) - const FSEventStreamEventFlags c_interestingFlags = kFSEventStreamEventFlagItemCreated // for new folder/file + qCDebug(lcFolderWatcher) << "FolderWatcherPrivate::callback by OS X"; + + // These flags indicate that either due to system error or for unknown reasons, the entire + // directory structure must be rescanned (including files) + const auto c_fullScanFlags = kFSEventStreamEventFlagMustScanSubDirs + | kFSEventStreamEventFlagKernelDropped + | kFSEventStreamEventFlagUserDropped; + + for (int i = 0; i < static_cast(numEvents); ++i) { + const auto flag = eventFlags[i]; + if (flag & c_fullScanFlags) { + reinterpret_cast(clientCallBackInfo)->notifyAll(); + return; + } + } + + const auto c_interestingFlags = kFSEventStreamEventFlagItemCreated // for new folder/file | kFSEventStreamEventFlagItemRemoved // for rm | kFSEventStreamEventFlagItemInodeMetaMod // for mtime change | kFSEventStreamEventFlagItemRenamed // also coming for moves to trash in finder - | kFSEventStreamEventFlagItemModified; // for content change + | kFSEventStreamEventFlagItemModified // for content change + | kFSEventStreamEventFlagItemCloned; // for cloned items (since 10.13) //We ignore other flags, e.g. for owner change, xattr change, Finder label change etc - qCDebug(lcFolderWatcher) << "FolderWatcherPrivate::callback by OS X"; - QStringList paths; CFArrayRef eventPaths = (CFArrayRef)eventPathsVoid; for (int i = 0; i < static_cast(numEvents); ++i) { @@ -110,11 +124,11 @@ QStringList FolderWatcherPrivate::addCoalescedPaths(const QStringList &paths) co QStringList coalescedPaths; for (const auto &eventPath : paths) { if (QDir(eventPath).exists()) { - QDirIterator it(eventPath, QDir::AllDirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + QDirIterator it(eventPath, QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Files, QDirIterator::Subdirectories); while (it.hasNext()) { - auto subfolder = it.next(); - if (!paths.contains(subfolder)) { - coalescedPaths.append(subfolder); + const auto path = it.next(); + if (!paths.contains(path)) { + coalescedPaths.append(path); } } } @@ -128,5 +142,18 @@ void FolderWatcherPrivate::doNotifyParent(const QStringList &paths) _parent->changeDetected(totalPaths); } +void FolderWatcherPrivate::notifyAll() +{ + QDirIterator dirIterator(_folder, QDirIterator::Subdirectories); + QStringList allPaths; + + while(dirIterator.hasNext()) { + const auto dirEntry = dirIterator.next(); + allPaths.append(dirEntry); + } + + _parent->changeDetected(allPaths); +} + } // ns mirall diff --git a/src/gui/folderwatcher_mac.h b/src/gui/folderwatcher_mac.h index e68124f824326..b2d9eaa40452d 100644 --- a/src/gui/folderwatcher_mac.h +++ b/src/gui/folderwatcher_mac.h @@ -36,6 +36,7 @@ class FolderWatcherPrivate void startWatching(); QStringList addCoalescedPaths(const QStringList &) const; void doNotifyParent(const QStringList &); + void notifyAll(); /// On OSX the watcher is ready when the ctor finished. bool _ready = true;