Skip to content

Commit 0b8300a

Browse files
DiegosdrsDiego SindresDiego Sindres
authored
Feature/extension osm reader country dynamic (#1)
* feat: dynamic country_code support * Binary multi_country ready for PR * final change done after Damien review * add --version feature --------- Co-authored-by: Diego Sindres <diegosindres@MacBookPro.lan> Co-authored-by: Diego Sindres <diegosindres@MacBook-Pro-de-ODS.local>
1 parent 9a5bb60 commit 0b8300a

7 files changed

Lines changed: 135 additions & 44 deletions

File tree

.DS_Store

6 KB
Binary file not shown.

.github/workflows/rust.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ jobs:
3030

3131
- name: Create Release
3232
# https://github.com/softprops/action-gh-release
33+
if: github.event_name == 'push'
3334
uses: softprops/action-gh-release@v1
3435
with:
3536
files: target/x86_64-unknown-linux-musl/release/*
36-
tag_name: v1.1.0
37-
release_name: Release v1.1.0
37+
tag_name: v1.2.0
38+
release_name: Release v1.2.0

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
.envrc
22
.idea
33
target
4-
5-
4+
.DS_Store

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pbf_history_reader"
3-
version = "0.1.0"
3+
version = "1.2.0"
44
edition = "2021"
55

66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

README.md

Lines changed: 92 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# OpenStreetMap PBF history parser
2+
23
This Rust program:
34
- parses OSM [history files from Geofabrik](https://osm-internal.download.geofabrik.de)
4-
- then creates a postgres `osm.history` table with the following fields:
5+
- then creates a postgres `{schema}.history` table with the following fields:
56
- id (negative IDs are for relations)
67
- timestamps
78
- changesets
@@ -10,13 +11,41 @@ This Rust program:
1011
- users_number
1112
- versions_number
1213

14+
The database schema is dynamically computed based on the country code (see Usage section below).
15+
16+
---
17+
18+
## Usage
19+
20+
### Basic usage (France, default)
21+
```bash
22+
./pbf_history_reader /path/to/history.osh.pbf /path/to/tag_list.txt
23+
```
24+
Writes to schema `osm`.
25+
26+
### With country code (multi-country support)
27+
```bash
28+
./pbf_history_reader /path/to/history.osh.pbf /path/to/tag_list.txt nz
29+
```
30+
Writes to schema `osm_nz`.
31+
```bash
32+
./pbf_history_reader /path/to/history.osh.pbf /path/to/tag_list.txt au
33+
```
34+
Writes to schema `osm_au`.
35+
36+
### To know the version
37+
```bash
38+
./pbf_history_reader --version
39+
```
40+
41+
---
1342

1443
## Configure your rust environment
44+
1545
### Tools
1646

1747
Install `rust` and `cargo` with:
18-
19-
```
48+
```bash
2049
curl https://sh.rustup.rs -sSf | sh
2150
```
2251

@@ -26,74 +55,108 @@ curl https://sh.rustup.rs -sSf | sh
2655

2756
#### Building the executable file
2857
from the `osm/pbf_history_reader` subfolder
29-
````
58+
```
3059
cargo build
31-
````
60+
```
3261

3362
It creates an executable file in `./target/debug/` directory (by default, `cargo` builds in debug mode)
3463

3564
#### Building & running the executable file
36-
37-
````
65+
```
3866
cargo run
39-
````
67+
```
4068

4169
This command builds then run the executable file.
4270

4371
#### Building for release
44-
4572
```
4673
cargo build --release
4774
```
4875

4976
It creates an executable file in `./target/release/` directory. With this option, the program is optimized to run
5077
faster.
5178

52-
### Cross-compilation
79+
---
80+
81+
## Cross-compilation
5382

5483
- Install a cross toolchain:
5584

5685
On mac:
57-
5886
```
5987
brew tap SergioBenitez/osxct
6088
brew install x86_64-unknown-linux-gnu
6189
```
6290

6391
then specify it in cargo config file `.cargo/config.toml`:
64-
6592
```bash
6693
# .cargo/config.toml
6794
[target.x86_64-unknown-linux-gnu]
6895
linker = "/opt/homebrew/bin/x86_64-unknown-linux-gnu-gcc"
6996
```
7097

7198
- Specify the compilation target:
72-
7399
```
74100
rustup target add x86_64-unknown-linux-gnu
75101
```
76102

77103
- Compile (in release):
78-
79104
```
80105
cargo build --target x86_64-unknown-linux-gnu -v --release
81106
```
82107

83108
The executable file is created in `osm/pbf_history_reader/target/x86_64-unknown-linux-gnu/release` directory
84109

85-
> pbf_history_reader needs several environment variables to work:
86-
> - DB_NAME
87-
> - DB_PORT
88-
> - DB_USER
89-
>
90-
> (DB_NAME, DB_USER and DB_PORT have default values defined in `osm/pbf_history_reader/src/main.rs` file, but you can
91-
> override them (especially if you are working locally))
92-
> - DB_HOST
93-
> - DB_PASSWORD
94-
> - OSM_ACCOUNT_PASSWORD (for history files)
95-
> - OSM_ACCOUNT_USER
96-
>
97-
98-
> They can be provided with `env.local` or `.envrc` files (don't forget to pass them to the container
99-
> in `docker-compose.yml` file)
110+
---
111+
112+
## Environment variables
113+
114+
pbf_history_reader needs several environment variables to work:
115+
- `DB_HOST` (required)
116+
- `DB_PASSWORD` (required)
117+
- `DB_NAME` (default: `dataseed`)
118+
- `DB_PORT` (default: `5432`)
119+
- `DB_USER` (default: `dataseed`)
120+
- `OSM_ACCOUNT_USER` (for history files)
121+
- `OSM_ACCOUNT_PASSWORD` (for history files)
122+
123+
They can be provided with `env.local` or `.envrc` files (don't forget to pass them to the container
124+
in `docker-compose.yml` file)
125+
126+
---
127+
128+
## Release
129+
130+
### How to release a new version
131+
132+
1. **Update the version tag in `.github/workflows/rust.yml` and in `Cargo.toml`**
133+
134+
Edit the `tag_name` and `release_name` fields:
135+
```yaml
136+
- name: Create Release
137+
uses: softprops/action-gh-release@v1
138+
with:
139+
files: target/x86_64-unknown-linux-musl/release/*
140+
tag_name: v1.2.0 # ← update this
141+
release_name: Release v1.2.0 # ← and this
142+
```
143+
144+
Edit the `version` fields:
145+
```
146+
version = "1.2.0". # <- update this
147+
```
148+
149+
2. **Commit and push to master**
150+
```bash
151+
git add .github/workflows/rust.yml
152+
git commit -m "chore: bump version to v1.2.0"
153+
git push origin master
154+
```
155+
156+
3. **GitHub Actions will automatically:**
157+
- Build the binary for `x86_64-unknown-linux-musl`
158+
- Create a GitHub Release `v1.3.0` with the binary attached
159+
- The binary will be available at:
160+
```
161+
https://github.com/opendatasoft/osm-pbf-history-reader/releases/download/v1.2.0/pbf_history_reader
162+
```

src/main.rs

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,53 @@ mod infos;
1010
mod load_infos;
1111
mod postgres_client;
1212

13-
const SCHEMA: &str = "OSM";
1413
const TABLE: &str = "HISTORY";
1514

1615
fn main() {
16+
let args: Vec<String> = env::args().collect();
17+
if args.len() > 1 && args[1] == "--version" {
18+
println!("pbf_history_reader version: {}", env!("CARGO_PKG_VERSION"));
19+
return;
20+
}
1721
let host: String = env::var("DB_HOST").expect("$DB_HOST is not set");
1822
let password: String = env::var("DB_PASSWORD").expect("$DB_PASSWORD is not set");
1923
let user: String = env::var("DB_USER").unwrap_or(String::from("dataseed"));
2024
let dbname: String = env::var("DB_NAME").unwrap_or(String::from("dataseed"));
2125
let port: String = env::var("DB_PORT").unwrap_or(String::from("5432"));
2226

2327
let args: Vec<String> = env::args().collect();
28+
29+
if args.len() < 3 {
30+
panic!("Usage: {} <history_pbf> <tag_list> [country_code] (or --version)", args[0]);
31+
}
32+
2433
let history_file_path_str = &args[1];
2534
let history_file_path = Path::new(history_file_path_str);
2635

2736
let tag_list_file_path_str = &args[2];
2837
let tag_list_file_path = Path::new(tag_list_file_path_str);
2938

39+
// SECURITY if no 4th argument is send (old fr pipeline hardcoded)
40+
// If no country_code OR country_code = fr --> schema = osm
41+
// consistency with old version
42+
let country_code = args.get(3).cloned().unwrap_or_else(|| String::from("fr"));
43+
44+
if country_code.len() != 2 {
45+
panic!(
46+
"Invalid country_code '{}': must be exactly 2 letters (e.g., 'fr', 'au', 'nz')",
47+
country_code
48+
);
49+
}
50+
51+
let schema = if country_code == "fr" {
52+
String::from("osm")
53+
} else {
54+
format!("osm_{}", country_code)
55+
};
56+
3057
for path in [history_file_path, tag_list_file_path] {
3158
if !path.exists() {
32-
panic!("Tag list file {} does not exists", path.display())
59+
panic!("File {} does not exist", path.display())
3360
}
3461
}
3562

@@ -52,26 +79,27 @@ fn main() {
5279
}
5380
let tag_list: HashSet<&str> = tag_list_string.iter().map(|s| s.as_str()).collect();
5481

55-
println!("{:?}", tag_list);
82+
println!("Tags to filter: {:?}", tag_list);
83+
println!("Processing for country: {} (SQL schema: {})", country_code, schema);
5684

5785
let now = Instant::now();
5886
let mut db_client = postgres_client::connect(&host, &user, &password, &dbname, &port);
5987
let db_connection_time = Instant::now();
6088

61-
postgres_client::create_schema(&mut db_client, SCHEMA);
89+
postgres_client::create_schema(&mut db_client, &schema);
6290
let db_schema_creation_time = Instant::now();
6391

64-
postgres_client::create_table_history(&mut db_client, SCHEMA, TABLE);
92+
postgres_client::create_table_history(&mut db_client, &schema, TABLE);
6593
let db_history_creation_time = Instant::now();
6694

6795
let elements_infos =
6896
history_processing::process_history(history_file_path.to_str().unwrap(), tag_list);
6997
let process_history_time = Instant::now();
7098

71-
postgres_client::add_index(&mut db_client, SCHEMA, TABLE, "id");
99+
postgres_client::add_index(&mut db_client, &schema, TABLE, "id");
72100
let indexing_time = Instant::now();
73101

74-
load_infos::load(&mut db_client, SCHEMA, TABLE, elements_infos);
102+
load_infos::load(&mut db_client, &schema, TABLE, elements_infos);
75103
let insert_history_time = Instant::now();
76104

77105
println!(
@@ -91,4 +119,4 @@ fn main() {
91119
insert_history_time.duration_since(indexing_time),
92120
insert_history_time.duration_since(now),
93121
)
94-
}
122+
}

0 commit comments

Comments
 (0)