fix stat on Android, add operations to nan ctime mtime and undefined size

This commit is contained in:
fyears 2022-05-10 21:15:30 +08:00
parent 4e8bec9511
commit 28bd861c9e
5 changed files with 56 additions and 21 deletions

View File

@ -166,18 +166,20 @@ export const decryptBase64urlToString = async (
};
export const getSizeFromOrigToEnc = (x: number) => {
if (x < 0 || !Number.isInteger(x)) {
throw Error(`x=${x} is not a valid size`);
if (x < 0 || Number.isNaN(x) || !Number.isInteger(x)) {
throw Error(`getSizeFromOrigToEnc: x=${x} is not a valid size`);
}
return (Math.floor(x / 16) + 1) * 16 + 16;
};
export const getSizeFromEncToOrig = (x: number) => {
if (x < 32 || !Number.isInteger(x)) {
throw Error(`${x} is not a valid size`);
if (x < 32 || Number.isNaN(x) || !Number.isInteger(x)) {
throw Error(`getSizeFromEncToOrig: ${x} is not a valid size`);
}
if (x % 16 !== 0) {
throw Error(`${x} is not a valid encrypted file size`);
throw Error(
`getSizeFromEncToOrig: ${x} is not a valid encrypted file size`
);
}
return {
minSize: ((x - 16) / 16 - 1) * 16,

View File

@ -5,7 +5,7 @@ import { requireApiVersion, TAbstractFile, TFile, TFolder } from "obsidian";
import { API_VER_STAT_FOLDER, SUPPORTED_SERVICES_TYPE } from "./baseTypes";
import type { SyncPlanType } from "./sync";
import { toText, unixTimeToStr } from "./misc";
import { statFix, toText, unixTimeToStr } from "./misc";
import { log } from "./moreOnLog";
@ -417,7 +417,7 @@ export const insertRenameRecordByVault = async (
if (requireApiVersion(API_VER_STAT_FOLDER)) {
// TAbstractFile does not contain these info
// but from API_VER_STAT_FOLDER we can manually stat them by path.
const s = await fileOrFolder.vault.adapter.stat(fileOrFolder.path);
const s = await statFix(fileOrFolder.vault, fileOrFolder.path);
ctime = s.ctime;
mtime = s.mtime;
}

View File

@ -339,12 +339,9 @@ export const checkHasSpecialCharForDir = (x: string) => {
};
export const unixTimeToStr = (x: number | undefined | null) => {
if (x === undefined) {
if (x === undefined || x === null || Number.isNaN(x)) {
return undefined;
}
if (x === null) {
return null;
}
return window.moment(x).format() as string;
};
@ -408,3 +405,25 @@ export const toText = (x: any) => {
return `${x}`;
}
};
/**
* On Android the stat has bugs for folders. So we need a fixed version.
* @param vault
* @param path
*/
export const statFix = async (vault: Vault, path: string) => {
const s = await vault.adapter.stat(path);
if (s.ctime === undefined || s.ctime === null || Number.isNaN(s.ctime)) {
s.ctime = undefined;
}
if (s.mtime === undefined || s.mtime === null || Number.isNaN(s.mtime)) {
s.mtime = undefined;
}
if (
(s.size === undefined || s.size === null || Number.isNaN(s.size)) &&
s.type === "folder"
) {
s.size = 0;
}
return s;
};

View File

@ -2,6 +2,7 @@ import { Vault, Stat, ListedFiles } from "obsidian";
import { Queue } from "@fyears/tsqueue";
import chunk from "lodash/chunk";
import flatten from "lodash/flatten";
import { statFix } from "./misc";
export interface ObsConfigDirFileType {
key: string;
@ -12,7 +13,7 @@ export interface ObsConfigDirFileType {
}
const isFolderToSkip = (x: string) => {
let specialFolders = [".git", ".svn", "node_modules"];
let specialFolders = [".git", ".github", ".gitlab", ".svn", "node_modules"];
for (const iterator of specialFolders) {
if (
x === iterator ||
@ -75,7 +76,8 @@ export const listFilesInObsFolder = async (
const itemsToFetchChunks = chunk(itemsToFetch, CHUNK_SIZE);
for (const singleChunk of itemsToFetchChunks) {
const r = singleChunk.map(async (x) => {
const statRes = await vault.adapter.stat(x);
const statRes = await statFix(vault, x);
const isFolder = statRes.type === "folder";
let children: ListedFiles = undefined;
if (isFolder) {

View File

@ -37,6 +37,7 @@ import {
getParentFolder,
atWhichLevel,
unixTimeToStr,
statFix,
} from "./misc";
import { RemoteClient } from "./remote";
import {
@ -336,7 +337,7 @@ const ensembleMixedStates = async (
// ignore
continue;
} else if (entry instanceof TFile) {
const mtimeLocal = Math.max(entry.stat.mtime || 0, entry.stat.ctime || 0);
const mtimeLocal = Math.max(entry.stat.mtime ?? 0, entry.stat.ctime ?? 0);
r = {
key: entry.path,
existLocal: true,
@ -380,7 +381,10 @@ const ensembleMixedStates = async (
if (syncConfigDir && localConfigDirContents !== undefined) {
for (const entry of localConfigDirContents) {
const key = entry.key;
const mtimeLocal = Math.max(entry.mtime, entry.ctime);
let mtimeLocal = Math.max(entry.mtime ?? 0, entry.ctime ?? 0);
if (Number.isNaN(mtimeLocal) || mtimeLocal === 0) {
mtimeLocal = undefined;
}
const r: FileOrFolderMixedState = {
key: key,
existLocal: true,
@ -468,10 +472,13 @@ const ensembleMixedStates = async (
changeLocalMtimeUsingMapping: true,
};
if (results.hasOwnProperty(key)) {
const mtimeLocal = Math.max(
r.mtimeLocal || 0,
results[key].mtimeLocal || 0
let mtimeLocal = Math.max(
r.mtimeLocal ?? 0,
results[key].mtimeLocal ?? 0
);
if (Number.isNaN(mtimeLocal) || mtimeLocal === 0) {
mtimeLocal = undefined;
}
results[key].mtimeLocal = mtimeLocal;
results[key].mtimeLocalFmt = unixTimeToStr(mtimeLocal);
results[key].changeLocalMtimeUsingMapping =
@ -838,9 +845,14 @@ const assignOperationToFolderInplace = async (
// if it was created after deletion, we should keep it as is
if (requireApiVersion(API_VER_STAT_FOLDER)) {
if (r.existLocal) {
const { ctime, mtime } = await vault.adapter.stat(r.key);
const cmtime = Math.max(ctime, mtime);
if (cmtime > 0 && cmtime >= deltimeLocal && cmtime >= deltimeRemote) {
const { ctime, mtime } = await statFix(vault, r.key);
const cmtime = Math.max(ctime ?? 0, mtime ?? 0);
if (
!Number.isNaN(cmtime) &&
cmtime > 0 &&
cmtime >= deltimeLocal &&
cmtime >= deltimeRemote
) {
keptFolder.add(getParentFolder(r.key));
if (r.existLocal && r.existRemote) {
r.decision = "skipFolder";