From 7534c16fef24ec176decb3da695322ce87c8dfb0 Mon Sep 17 00:00:00 2001
From: Kubat <mael.martin31@gmail.com>
Date: Sat, 1 Oct 2022 21:38:14 +0200
Subject: [PATCH] RUST: Run the diesel run migration command on a non existing
 db and generate the schema.rs file if needed

NOTE: A build.rs file should not write files in the source folder, but
      it's easier to do it that way for now. We migh want to do
      something with cmake otherwise...
---
 README.md                                     |  8 ++-
 src/rust/liblektor-rs/Cargo.toml              |  2 +-
 src/rust/liblektor-rs/build.rs                | 54 +++++++++++++++++++
 src/rust/liblektor-rs/diesel.toml             |  2 +-
 src/rust/liblektor-rs/migrations/.keep        |  0
 .../down.sql                                  |  1 -
 .../up.sql                                    | 12 ++---
 src/rust/liblektor-rs/src/database/mod.rs     |  4 ++
 src/rust/liblektor-rs/src/database/models.rs  | 11 ++++
 .../liblektor-rs/src/{ => database}/schema.rs | 30 +++++++++++
 src/rust/liblektor-rs/src/lib.rs              |  3 +-
 src/rust/liblektor-rs/src/mkv.rs              | 12 -----
 12 files changed, 112 insertions(+), 27 deletions(-)
 create mode 100644 src/rust/liblektor-rs/build.rs
 delete mode 100644 src/rust/liblektor-rs/migrations/.keep
 rename src/rust/liblektor-rs/migrations/{2022-09-30-204512_create_posts => 2022-09-30-204512_initial}/down.sql (88%)
 rename src/rust/liblektor-rs/migrations/{2022-09-30-204512_create_posts => 2022-09-30-204512_initial}/up.sql (82%)
 create mode 100644 src/rust/liblektor-rs/src/database/models.rs
 rename src/rust/liblektor-rs/src/{ => database}/schema.rs (58%)
 delete mode 100644 src/rust/liblektor-rs/src/mkv.rs

diff --git a/README.md b/README.md
index 11f5616b..73c7e1fb 100644
--- a/README.md
+++ b/README.md
@@ -62,7 +62,13 @@ If you are developping for lektor, you will need the
 [clang-format](https://releases.llvm.org/download.html) command line utility,
 for a beautifull and uniform C++ code style.
 [Here](https://clang.llvm.org/docs/ClangFormatStyleOptions.html) is the list of
-all the options to put in the `.clang-format` file.
+all the options to put in the `.clang-format` file. You will also need diesel
+for all the database stuff, use the following command to install diesel cli with
+the correct sqlite support on your system:
+
+```sh
+cargo install diesel_cli --no-default-features --features sqlite
+```
 
 ### Building instructions
 
diff --git a/src/rust/liblektor-rs/Cargo.toml b/src/rust/liblektor-rs/Cargo.toml
index 58bfc571..7e9d12c7 100644
--- a/src/rust/liblektor-rs/Cargo.toml
+++ b/src/rust/liblektor-rs/Cargo.toml
@@ -8,4 +8,4 @@ crate-type = [ "staticlib" ]
 
 [dependencies]
 libc   = "0.2.0"
-diesel = { version = "2", features = [ "sqlite" ] }
\ No newline at end of file
+diesel = { version = "2", default-features = false, features = [ "sqlite" ] }
diff --git a/src/rust/liblektor-rs/build.rs b/src/rust/liblektor-rs/build.rs
new file mode 100644
index 00000000..91f293db
--- /dev/null
+++ b/src/rust/liblektor-rs/build.rs
@@ -0,0 +1,54 @@
+use std::{
+    env,
+    path::Path,
+    process::{Command, Stdio},
+};
+
+macro_rules! cmd {
+    ($exec: literal => $args: tt) => {{
+        let output = Command::new($exec)
+            .args($args)
+            .stdout(Stdio::piped())
+            .spawn()
+            .expect(format!("failed to run {}", $exec).as_str())
+            .wait_with_output()
+            .expect(format!("failed to wait for {}", $exec).as_str());
+        assert!(output.status.success());
+    }};
+}
+
+fn rerun_directory<T: AsRef<Path> + ?Sized>(dir: &T) {
+    println!("cargo:rerun-if-changed={}", dir.as_ref().to_string_lossy());
+    for entry in std::fs::read_dir(dir).unwrap() {
+        let path = entry.expect("Couldn't access file in src directory").path();
+        if path.is_dir() {
+            rerun_directory(&path);
+        }
+    }
+}
+
+fn main() {
+    // Because the target folder was fixed, we know where the source folder is!
+    let out_dir = env::var_os("OUT_DIR").unwrap();
+    let out_dir = Path::new(&out_dir);
+    let db_path = out_dir
+        .join("kara.db")
+        .canonicalize()
+        .expect("failed to canonicalize the sample kara database path");
+    let source_dir = out_dir
+        .join("../../../../../liblektor-rs")
+        .canonicalize()
+        .expect("failed to canonicalize the source path");
+    let migration_dir = source_dir
+        .join("migrations")
+        .canonicalize()
+        .expect("failed to canonicalize the migration dir");
+
+    let _ = std::fs::remove_file(&db_path);
+    env::set_var("DATABASE_URL", db_path);
+    env::set_current_dir(source_dir).expect("failed to cwd to source folder!");
+    cmd!( "diesel" => [ "migration", "run" ] );
+
+    rerun_directory(&migration_dir);
+    println!("cargo:rerun-if-changed=build.rs");
+}
diff --git a/src/rust/liblektor-rs/diesel.toml b/src/rust/liblektor-rs/diesel.toml
index 35a12ff0..8de80930 100644
--- a/src/rust/liblektor-rs/diesel.toml
+++ b/src/rust/liblektor-rs/diesel.toml
@@ -2,7 +2,7 @@
 # see https://diesel.rs/guides/configuring-diesel-cli
 
 [print_schema]
-file = "src/schema.rs"
+file = "src/database/schema.rs"
 
 [migrations_directory]
 dir = "migrations"
diff --git a/src/rust/liblektor-rs/migrations/.keep b/src/rust/liblektor-rs/migrations/.keep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/rust/liblektor-rs/migrations/2022-09-30-204512_create_posts/down.sql b/src/rust/liblektor-rs/migrations/2022-09-30-204512_initial/down.sql
similarity index 88%
rename from src/rust/liblektor-rs/migrations/2022-09-30-204512_create_posts/down.sql
rename to src/rust/liblektor-rs/migrations/2022-09-30-204512_initial/down.sql
index 5a2e3600..9a50b906 100644
--- a/src/rust/liblektor-rs/migrations/2022-09-30-204512_create_posts/down.sql
+++ b/src/rust/liblektor-rs/migrations/2022-09-30-204512_initial/down.sql
@@ -5,5 +5,4 @@ DROP TABLE kara_makers;
 DROP TABLE kara_tag;
 DROP TABLE tag;
 DROP TABLE kara_tags;
-DROP TABLE queue_1;
 DROP TABLE history;
diff --git a/src/rust/liblektor-rs/migrations/2022-09-30-204512_create_posts/up.sql b/src/rust/liblektor-rs/migrations/2022-09-30-204512_initial/up.sql
similarity index 82%
rename from src/rust/liblektor-rs/migrations/2022-09-30-204512_create_posts/up.sql
rename to src/rust/liblektor-rs/migrations/2022-09-30-204512_initial/up.sql
index 33a7c418..a4ec97be 100644
--- a/src/rust/liblektor-rs/migrations/2022-09-30-204512_create_posts/up.sql
+++ b/src/rust/liblektor-rs/migrations/2022-09-30-204512_initial/up.sql
@@ -1,6 +1,6 @@
 CREATE TABLE repo
-  ( name TEXT    NOT NULL
-  , id   INTEGER NOT NULL
+  ( id   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT
+  , name TEXT    NOT NULL UNIQUE
   );
 
 CREATE TABLE repo_kara
@@ -29,7 +29,7 @@ CREATE TABLE kara_makers
 
 CREATE TABLE tag
   ( id   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT
-  , name TEXT    NOT NULL
+  , name TEXT    NOT NULL UNIQUE
   );
 
 CREATE TABLE kara_tags
@@ -39,13 +39,7 @@ CREATE TABLE kara_tags
   , PRIMARY KEY (kara_id, tag_id, value)
   );
 
-CREATE TABLE queue_1
-  ( id       INTEGER NOT NULL REFERENCES kara(id) ON DELETE CASCADE
-  , position INTEGER NOT NULL CHECK(position > 0)
-  );
-
 CREATE TABLE history
   ( id      INTEGER NOT NULL REFERENCES kara(id) ON DELETE CASCADE
   , epoch   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT
-  , PRIMARY KEY (id, epoch)
   );
diff --git a/src/rust/liblektor-rs/src/database/mod.rs b/src/rust/liblektor-rs/src/database/mod.rs
index e69de29b..8ea4ab39 100644
--- a/src/rust/liblektor-rs/src/database/mod.rs
+++ b/src/rust/liblektor-rs/src/database/mod.rs
@@ -0,0 +1,4 @@
+pub(self) use diesel::prelude::*;
+
+pub mod models;
+pub mod schema;
diff --git a/src/rust/liblektor-rs/src/database/models.rs b/src/rust/liblektor-rs/src/database/models.rs
new file mode 100644
index 00000000..d6727d48
--- /dev/null
+++ b/src/rust/liblektor-rs/src/database/models.rs
@@ -0,0 +1,11 @@
+use crate::database::{schema::*, *};
+
+#[derive(Insertable)]
+#[diesel(table_name = kara)]
+pub struct NewKara<'a> {
+    pub song_title: &'a str,
+    pub song_type: &'a str,
+    pub song_origin: &'a str,
+    pub source_name: &'a str,
+    pub language: &'a str,
+}
diff --git a/src/rust/liblektor-rs/src/schema.rs b/src/rust/liblektor-rs/src/database/schema.rs
similarity index 58%
rename from src/rust/liblektor-rs/src/schema.rs
rename to src/rust/liblektor-rs/src/database/schema.rs
index fda66f55..f429bd48 100644
--- a/src/rust/liblektor-rs/src/schema.rs
+++ b/src/rust/liblektor-rs/src/database/schema.rs
@@ -1,13 +1,22 @@
 // @generated automatically by Diesel CLI.
 
+diesel::table! {
+    history (epoch) {
+        id -> Integer,
+        epoch -> Integer,
+    }
+}
+
 diesel::table! {
     kara (id) {
         id -> Integer,
+        is_dl -> Bool,
         song_title -> Text,
         song_type -> Text,
         song_origin -> Text,
         source_name -> Text,
         language -> Text,
+        kara_hash -> Text,
     }
 }
 
@@ -26,6 +35,21 @@ diesel::table! {
     }
 }
 
+diesel::table! {
+    repo (id) {
+        id -> Integer,
+        name -> Text,
+    }
+}
+
+diesel::table! {
+    repo_kara (repo_id, repo_kara_id, local_kara_id) {
+        repo_id -> Integer,
+        repo_kara_id -> Integer,
+        local_kara_id -> Integer,
+    }
+}
+
 diesel::table! {
     tag (id) {
         id -> Integer,
@@ -33,13 +57,19 @@ diesel::table! {
     }
 }
 
+diesel::joinable!(history -> kara (id));
 diesel::joinable!(kara_makers -> kara (id));
 diesel::joinable!(kara_tags -> kara (kara_id));
 diesel::joinable!(kara_tags -> tag (tag_id));
+diesel::joinable!(repo_kara -> kara (local_kara_id));
+diesel::joinable!(repo_kara -> repo (repo_id));
 
 diesel::allow_tables_to_appear_in_same_query!(
+    history,
     kara,
     kara_makers,
     kara_tags,
+    repo,
+    repo_kara,
     tag,
 );
diff --git a/src/rust/liblektor-rs/src/lib.rs b/src/rust/liblektor-rs/src/lib.rs
index a691be2f..a40f844b 100644
--- a/src/rust/liblektor-rs/src/lib.rs
+++ b/src/rust/liblektor-rs/src/lib.rs
@@ -1,8 +1,7 @@
-#![allow(dead_code)]
+#![allow(dead_code, unused_imports)]
 
 mod compat;
 mod database;
-mod mkv;
 mod module;
 
 pub(crate) use compat::*;
diff --git a/src/rust/liblektor-rs/src/mkv.rs b/src/rust/liblektor-rs/src/mkv.rs
deleted file mode 100644
index 3770013e..00000000
--- a/src/rust/liblektor-rs/src/mkv.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-use crate::*;
-
-#[repr(C)]
-pub(crate) struct LktKaraMetadata {
-    song_name: [c_char; LEKTOR_TAG_MAX],
-    source_name: [c_char; LEKTOR_TAG_MAX],
-    category: [c_char; LEKTOR_TAG_MAX],
-    language: [c_char; LEKTOR_TAG_MAX],
-    author_name: [c_char; LEKTOR_TAG_MAX],
-    song_type: [c_char; LEKTOR_TAG_MAX],
-    song_number: c_int,
-}
-- 
GitLab