Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions build-linux.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
OUTPUT_DIR="${SCRIPT_DIR}/dist"
BUNDLES="deb,appimage"
TARGET=""
SKIP_BUILD=0

usage() {
cat <<'EOF'
Build Linux bundles for Cloudreve Desktop.

Usage:
./build-linux.sh [--skip-build] [--targets deb,appimage] [--target <rust-target>] [--output-dir <dir>]

Options:
--skip-build Skip `cargo tauri build` and only collect existing artifacts.
--targets <list> Tauri bundle targets (default: deb,appimage).
--target <triple> Rust target triple, e.g. x86_64-unknown-linux-gnu.
--output-dir <path> Output directory for collected bundle artifacts (default: ./dist).
-h, --help Show this help.
EOF
}

while [[ $# -gt 0 ]]; do
case "$1" in
--skip-build) SKIP_BUILD=1; shift ;;
--targets) BUNDLES="${2:-}"; shift 2 ;;
--target) TARGET="${2:-}"; shift 2 ;;
--output-dir) OUTPUT_DIR="${2:-}"; shift 2 ;;
-h|--help) usage; exit 0 ;;
*) echo "Unknown argument: $1" >&2; usage; exit 1 ;;
esac
done

if [[ "${SKIP_BUILD}" -eq 0 ]]; then
echo "Building Linux bundles (targets: ${BUNDLES})..."
pushd "${SCRIPT_DIR}" >/dev/null
if [[ -n "${TARGET}" ]]; then
cargo tauri build --target "${TARGET}" --bundles "${BUNDLES}"
else
cargo tauri build --bundles "${BUNDLES}"
fi
popd >/dev/null
else
echo "Skipping build step."
fi

mkdir -p "${OUTPUT_DIR}"

declare -a bundle_roots=()
if [[ -n "${TARGET}" ]]; then
bundle_roots+=("${SCRIPT_DIR}/target/${TARGET}/release/bundle")
bundle_roots+=("${SCRIPT_DIR}/src-tauri/target/${TARGET}/release/bundle")
else
bundle_roots+=("${SCRIPT_DIR}/target/release/bundle")
bundle_roots+=("${SCRIPT_DIR}/src-tauri/target/release/bundle")
fi

copied=0
for root in "${bundle_roots[@]}"; do
[[ -d "${root}" ]] || continue
while IFS= read -r -d '' artifact; do
cp -f "${artifact}" "${OUTPUT_DIR}/"
copied=$((copied + 1))
done < <(find "${root}" -type f \( -name "*.deb" -o -name "*.AppImage" -o -name "*.rpm" -o -name "*.tar.gz" \) -print0)
done

if [[ "${copied}" -eq 0 ]]; then
echo "No bundle artifacts found. Checked:" >&2
printf ' %s\n' "${bundle_roots[@]}" >&2
exit 1
fi

echo "Collected ${copied} artifact(s) to ${OUTPUT_DIR}:"
find "${OUTPUT_DIR}" -maxdepth 1 -type f | sed 's|^| |'
6 changes: 4 additions & 2 deletions crates/cloudreve-api/src/api/explorer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -802,8 +802,10 @@ pub trait FileEventsApi {
///
/// while let Some(event) = subscription.next_event().await? {
/// match event {
/// cloudreve_api::models::explorer::FileEvent::Event(data) => {
/// println!("File event: {:?} on {}", data.event_type, data.from);
/// cloudreve_api::models::explorer::FileEvent::Event(events) => {
/// for data in events {
/// println!("File event: {:?} on {}", data.event_type, data.from);
/// }
/// }
/// _ => {}
/// }
Expand Down
4 changes: 2 additions & 2 deletions crates/cloudreve-api/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,10 @@ impl Client {
///
/// # Example
/// ```no_run
/// use cloudreve_api::{Client, ClientConfig};
/// use std::sync::Arc;
/// use std::pin::Pin;
/// use std::future::Future;
///
/// let mut client = Client::new(ClientConfig::new("https://example.com"));
/// client.set_on_credential_refreshed(Arc::new(|token| {
/// Box::pin(async move {
/// // Save token to storage
Expand Down
1 change: 1 addition & 0 deletions crates/cloudreve-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//!
//! ```no_run
//! use cloudreve_api::{Client, ClientConfig};
//! use cloudreve_api::api::UserApi;
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
Expand Down
15 changes: 11 additions & 4 deletions crates/cloudreve-sync/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ sha2 = "0.10"
image = "0.24"
url = "2.5"
cloudreve-api = { path = "../cloudreve-api" }
windows-core = "0.58.0"
nt-time = "0.8.0"
widestring = "1.0.2"
flagset = "0.4.5"
memoffset = "0.9.1"
chrono = "0.4.42"
Expand All @@ -43,9 +41,13 @@ aes = "0.8"
ctr = "0.9"
tokio-util = { version = "0.7", features = ["io"] }
globset = "0.4"

[target.'cfg(target_os = "windows")'.dependencies]
windows-core = "0.58.0"
widestring = "1.0.2"
win32_notif = { path = "../win32_notif" }

[dependencies.windows]
[target.'cfg(target_os = "windows")'.dependencies.windows]
version = "0.58.0"
features = [
"implement",
Expand Down Expand Up @@ -79,9 +81,14 @@ features = [
"Win32_UI_Notifications",
]

[build-dependencies]
[target.'cfg(target_os = "windows")'.build-dependencies]
windows = { version = "0.58.0", features = ["Win32_Foundation"] }

[target.'cfg(target_os = "linux")'.dependencies]
fuser = "0.16"
libc = "0.2"
notify-rust = "4.11"

[dependencies.uuid]
version = "1.6"
features = ["v4", "serde"]
Expand Down
19 changes: 19 additions & 0 deletions crates/cloudreve-sync/src/cfapi_linux/filter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
pub mod ticket {
use crate::cfapi::utility::WriteAt;
use std::io;

#[derive(Debug, Clone, Default)]
pub struct FetchData;

impl FetchData {
pub fn report_progress(&self, _total: u64, _transferred: u64) -> io::Result<()> {
Ok(())
}
}

impl WriteAt for FetchData {
fn write_at(&self, _data: &[u8], _offset: u64) -> io::Result<()> {
Ok(())
}
}
}
38 changes: 38 additions & 0 deletions crates/cloudreve-sync/src/cfapi_linux/metadata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use nt_time::FileTime;

#[derive(Debug, Clone, Copy, Default)]
pub struct Metadata;

impl Metadata {
pub fn file() -> Self {
Self
}

pub fn directory() -> Self {
Self
}

pub fn created(self, _time: FileTime) -> Self {
self
}

pub fn accessed(self, _time: FileTime) -> Self {
self
}

pub fn written(self, _time: FileTime) -> Self {
self
}

pub fn changed(self, _time: FileTime) -> Self {
self
}

pub fn size(self, _size: u64) -> Self {
self
}

pub fn attributes(self, _attributes: u32) -> Self {
self
}
}
5 changes: 5 additions & 0 deletions crates/cloudreve-sync/src/cfapi_linux/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod filter;
pub mod metadata;
pub mod placeholder;
pub mod placeholder_file;
pub mod utility;
142 changes: 142 additions & 0 deletions crates/cloudreve-sync/src/cfapi_linux/placeholder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
use std::fs;
use std::ops::RangeBounds;
use std::path::{Path, PathBuf};
use std::time::SystemTime;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum PinState {
#[default]
Unspecified,
Pinned,
Unpinned,
Excluded,
Inherit,
}

#[derive(Debug, Clone)]
pub struct LocalFileInfo {
pub exists: bool,
pub is_directory: bool,
pub file_size: Option<u64>,
pub last_modified: Option<SystemTime>,
}

impl LocalFileInfo {
pub fn missing() -> Self {
Self {
exists: false,
is_directory: false,
file_size: None,
last_modified: None,
}
}

pub fn from_path(path: &Path) -> std::io::Result<Self> {
match fs::metadata(path) {
Ok(meta) => Ok(Self {
exists: true,
is_directory: meta.is_dir(),
file_size: meta.is_file().then_some(meta.len()),
last_modified: meta.modified().ok(),
}),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(Self::missing()),
Err(e) => Err(e),
}
}

pub fn in_sync(&self) -> bool {
false
}

pub fn is_placeholder(&self) -> bool {
false
}

pub fn partial_on_disk(&self) -> bool {
false
}

pub fn pinned(&self) -> PinState {
PinState::Unspecified
}

pub fn is_directory(&self) -> bool {
self.is_directory
}

pub fn is_folder_populated(&self) -> bool {
self.exists && self.is_directory
}
}

#[derive(Debug, Clone)]
pub struct OpenOptions;

impl OpenOptions {
pub fn new() -> Self {
Self
}

pub fn exclusive(self) -> Self {
self
}

pub fn write_access(self) -> Self {
self
}

pub fn delete_access(self) -> Self {
self
}

pub fn foreground(self) -> Self {
self
}

pub fn open_win32(self, path: impl AsRef<Path>) -> std::io::Result<Placeholder> {
Ok(Placeholder {
path: path.as_ref().to_path_buf(),
})
}

pub fn open(self, path: impl AsRef<Path>) -> std::io::Result<Placeholder> {
Ok(Placeholder {
path: path.as_ref().to_path_buf(),
})
}

pub async fn open_win32_with_retry(
self,
path: impl AsRef<Path>,
) -> std::io::Result<Placeholder> {
Ok(Placeholder {
path: path.as_ref().to_path_buf(),
})
}

pub async fn open_with_retry(self, path: impl AsRef<Path>) -> std::io::Result<Placeholder> {
Ok(Placeholder {
path: path.as_ref().to_path_buf(),
})
}
}

#[derive(Debug, Clone)]
pub struct Placeholder {
#[allow(dead_code)]
path: PathBuf,
}

impl Placeholder {
pub fn hydrate(&mut self, _range: impl RangeBounds<u64>) -> std::io::Result<()> {
Ok(())
}

pub fn dehydrate(&mut self, _range: impl RangeBounds<u64>) -> std::io::Result<()> {
Ok(())
}

pub fn mark_in_sync(&mut self, _in_sync: bool, _usn: Option<i64>) -> std::io::Result<()> {
Ok(())
}
}
Loading