Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: use consistent relative paths for resources #2683

Conversation

lincolnthalles
Copy link
Contributor

  • always store resources with a relative path with forward slashes, which will be transformed as needed when the file is accessed

  • fix an issue with thumbnail generation on Windows

  • add several validations for local storage setting

  • improve front-end error feedback when changing local storage

  • add migrations to make existing resource paths relative (not needed, as the back-end code allows mixed path styles, but improves database consistency)

This improves data portability by a lot.

Migration queries testing

There are some differences between the 3 DBMS, but they are covered and the results are consistent.

Standard Memos Docker installations will work just fine, and most edge cases are covered.

image

SQLite

https://extendsclass.com/sqlite-browser.html

-- SQLite test
DROP TABLE IF EXISTS resource;
CREATE TABLE
  IF NOT EXISTS resource (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    filename TEXT NOT NULL DEFAULT '',
    internal_path TEXT NOT NULL DEFAULT '',
    old_internal_path TEXT
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'docker_abs.jpg',
    '/var/opt/memos/assets/202312/1703701008_docker.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'docker_rel.jpg',
    'assets/202312/1703701008_docker.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'docker_no_assets_prefix.jpg',
    '/var/opt/memos/202312/1703701008_docker.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'docker_rel_no_assets_prefix.jpg',
    '202312/1703701008_docker.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'windows_abs.jpg',
    'C:\ProgramData\memos\assets\202312\1703701008_windows.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'windows_rel.jpg',
    'assets\202312\1703701008_windows.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'windows_no_assets_prefix.jpg',
    'C:\ProgramData\memos\202312\1703701008_windows.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'windows_rel_no_assets_prefix.jpg',
    '202312\1703701008_windows.jpg'
  );

UPDATE resource
SET
  old_internal_path = internal_path;

-- Memos-compatible queries
--
UPDATE resource
SET
  internal_path = REPLACE (internal_path, '\', '/')
WHERE
  internal_path LIKE '%assets\%';

UPDATE resource
SET
  internal_path = REPLACE (
    internal_path,
    SUBSTR (
      internal_path,
      1,
      INSTR (internal_path, '/assets')
    ),
    ''
  );

-- / Memos-compatible queries

-- Show results
SELECT
  id,
  filename,
  old_internal_path,
  internal_path
FROM
  resource
ORDER BY id ASC;
MySQL

https://extendsclass.com/mysql-online.html

DROP TABLE IF EXISTS `resource`;
CREATE TABLE IF NOT exists `resource` (
  `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `filename` TEXT NOT NULL,
  `internal_path` VARCHAR(256) NOT NULL DEFAULT '',
  `old_internal_path` TEXT
);

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'docker_abs.jpg',
    '/var/opt/memos/assets/202312/1703701008_docker.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'docker_rel.jpg',
    'assets/202312/1703701008_docker.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'docker_no_assets_prefix.jpg',
    '/var/opt/memos/202312/1703701008_docker.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'docker_rel_no_assets_prefix.jpg',
    '202312/1703701008_docker.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'windows_abs.jpg',
    'C:\\ProgramData\\memos\\assets\\202312\\1703701008_windows.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'windows_rel.jpg',
    'assets\\202312\\1703701008_windows.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'windows_no_assets_prefix.jpg',
    'C:\\ProgramData\\memos\\202312\\1703701008_windows.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'windows_rel_no_assets_prefix.jpg',
    '202312\\1703701008_windows.jpg'
  );

UPDATE resource
SET
  old_internal_path = internal_path;

-- Memos-compatible queries
--
UPDATE resource
SET
  internal_path = REPLACE (internal_path, '\\', '/')
WHERE
  internal_path LIKE '%assets\\\%';

UPDATE resource
SET
  internal_path = REPLACE (
    internal_path,
    SUBSTR (
      internal_path,
      1,
      INSTR (internal_path, '/assets')
    ),
    ''
  );

-- / Memos-compatible queries

-- Show results
SELECT
  id,
  filename,
  old_internal_path,
  internal_path
FROM
  resource
ORDER BY id ASC;
PostgreSQL

https://extendsclass.com/postgresql-online.html

DROP TABLE IF EXISTS resource;
CREATE TABLE IF NOT exists resource (
  id SERIAL PRIMARY KEY,
  filename TEXT NOT NULL,
  internal_path TEXT NOT NULL DEFAULT '',
  old_internal_path TEXT
);

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'docker_abs.jpg',
    '/var/opt/memos/assets/202312/1703701008_docker.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'docker_rel.jpg',
    'assets/202312/1703701008_docker.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'docker_no_assets_prefix.jpg',
    '/var/opt/memos/202312/1703701008_docker.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'docker_rel_no_assets_prefix.jpg',
    '202312/1703701008_docker.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'windows_abs.jpg',
    'C:\ProgramData\memos\assets\202312\1703701008_windows.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'windows_rel.jpg',
    'assets\202312\1703701008_windows.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'windows_no_assets_prefix.jpg',
    'C:\ProgramData\memos\202312\1703701008_windows.jpg'
  );

INSERT INTO
  resource (filename, internal_path)
VALUES
  (
    'windows_rel_no_assets_prefix.jpg',
    '202312\1703701008_windows.jpg'
  );

UPDATE resource
SET
  old_internal_path = internal_path;

-- Memos-compatible queries
--
UPDATE resource
SET
  internal_path = REPLACE (internal_path, '\', '/')
WHERE
  internal_path LIKE '%assets\\%';

UPDATE resource
SET
  internal_path = REPLACE (
    internal_path,
    SUBSTRING(
      internal_path
      FROM
        1 FOR POSITION('/assets' IN internal_path)
    ),
    ''
  );
-- / Memos-compatible queries

-- Show results
SELECT
  id,
  filename,
  old_internal_path,
  internal_path
FROM
  resource
ORDER BY id ASC;

- always store resources with a relative path with forward slashes, which will be transformed as needed when the file is accessed

- fix an issue with thumbnail generation on Windows

- add several validations for local storage setting

- improve front-end error feedback when changing local storage

- add migrations to make existing resource paths relative (not needed, but improves database consistency)
Copy link
Collaborator

@boojack boojack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, great point!

@boojack boojack merged commit 411e807 into usememos:main Dec 28, 2023
7 checks passed
@lincolnthalles lincolnthalles deleted the chore--use-relative-paths-for-resource-storage branch January 14, 2024 16:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants