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) => { export const getSizeFromOrigToEnc = (x: number) => {
if (x < 0 || !Number.isInteger(x)) { if (x < 0 || Number.isNaN(x) || !Number.isInteger(x)) {
throw Error(`x=${x} is not a valid size`); throw Error(`getSizeFromOrigToEnc: x=${x} is not a valid size`);
} }
return (Math.floor(x / 16) + 1) * 16 + 16; return (Math.floor(x / 16) + 1) * 16 + 16;
}; };
export const getSizeFromEncToOrig = (x: number) => { export const getSizeFromEncToOrig = (x: number) => {
if (x < 32 || !Number.isInteger(x)) { if (x < 32 || Number.isNaN(x) || !Number.isInteger(x)) {
throw Error(`${x} is not a valid size`); throw Error(`getSizeFromEncToOrig: ${x} is not a valid size`);
} }
if (x % 16 !== 0) { 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 { return {
minSize: ((x - 16) / 16 - 1) * 16, 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 { API_VER_STAT_FOLDER, SUPPORTED_SERVICES_TYPE } from "./baseTypes";
import type { SyncPlanType } from "./sync"; import type { SyncPlanType } from "./sync";
import { toText, unixTimeToStr } from "./misc"; import { statFix, toText, unixTimeToStr } from "./misc";
import { log } from "./moreOnLog"; import { log } from "./moreOnLog";
@ -417,7 +417,7 @@ export const insertRenameRecordByVault = async (
if (requireApiVersion(API_VER_STAT_FOLDER)) { if (requireApiVersion(API_VER_STAT_FOLDER)) {
// TAbstractFile does not contain these info // TAbstractFile does not contain these info
// but from API_VER_STAT_FOLDER we can manually stat them by path. // 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; ctime = s.ctime;
mtime = s.mtime; mtime = s.mtime;
} }

View File

@ -339,12 +339,9 @@ export const checkHasSpecialCharForDir = (x: string) => {
}; };
export const unixTimeToStr = (x: number | undefined | null) => { export const unixTimeToStr = (x: number | undefined | null) => {
if (x === undefined) { if (x === undefined || x === null || Number.isNaN(x)) {
return undefined; return undefined;
} }
if (x === null) {
return null;
}
return window.moment(x).format() as string; return window.moment(x).format() as string;
}; };
@ -408,3 +405,25 @@ export const toText = (x: any) => {
return `${x}`; 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 { Queue } from "@fyears/tsqueue";
import chunk from "lodash/chunk"; import chunk from "lodash/chunk";
import flatten from "lodash/flatten"; import flatten from "lodash/flatten";
import { statFix } from "./misc";
export interface ObsConfigDirFileType { export interface ObsConfigDirFileType {
key: string; key: string;
@ -12,7 +13,7 @@ export interface ObsConfigDirFileType {
} }
const isFolderToSkip = (x: string) => { const isFolderToSkip = (x: string) => {
let specialFolders = [".git", ".svn", "node_modules"]; let specialFolders = [".git", ".github", ".gitlab", ".svn", "node_modules"];
for (const iterator of specialFolders) { for (const iterator of specialFolders) {
if ( if (
x === iterator || x === iterator ||
@ -75,7 +76,8 @@ export const listFilesInObsFolder = async (
const itemsToFetchChunks = chunk(itemsToFetch, CHUNK_SIZE); const itemsToFetchChunks = chunk(itemsToFetch, CHUNK_SIZE);
for (const singleChunk of itemsToFetchChunks) { for (const singleChunk of itemsToFetchChunks) {
const r = singleChunk.map(async (x) => { const r = singleChunk.map(async (x) => {
const statRes = await vault.adapter.stat(x); const statRes = await statFix(vault, x);
const isFolder = statRes.type === "folder"; const isFolder = statRes.type === "folder";
let children: ListedFiles = undefined; let children: ListedFiles = undefined;
if (isFolder) { if (isFolder) {

View File

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