[Git][debian-gis-team/osm2pgsql][upstream] New upstream version 1.9.1+ds
Bas Couwenberg (@sebastic)
gitlab at salsa.debian.org
Wed Aug 23 04:39:02 BST 2023
Bas Couwenberg pushed to branch upstream at Debian GIS Project / osm2pgsql
Commits:
25898b2b by Bas Couwenberg at 2023-08-23T05:32:27+02:00
New upstream version 1.9.1+ds
- - - - -
20 changed files:
- .github/actions/ubuntu-prerequisites/action.yml
- .github/workflows/ci.yml
- CMakeLists.txt
- docs/osm2pgsql-replication.1
- docs/osm2pgsql.1
- scripts/osm2pgsql-replication
- src/flex-lua-expire-output.cpp
- src/geom.hpp
- src/lua-utils.cpp
- src/lua-utils.hpp
- src/output-pgsql.cpp
- src/table.hpp
- src/tagtransform-c.cpp
- tests/bdd/environment.py
- tests/bdd/flex/lua-expire-output-definitions.feature
- tests/bdd/steps/steps_db.py
- tests/bdd/steps/steps_execute.py
- tests/common-import.hpp
- tests/test-expire-from-geometry.cpp
- tests/test-output-pgsql-z_order.cpp
Changes:
=====================================
.github/actions/ubuntu-prerequisites/action.yml
=====================================
@@ -30,11 +30,15 @@ runs:
postgresql-${POSTGRESQL_VERSION}-postgis-${POSTGIS_VERSION} \
postgresql-${POSTGRESQL_VERSION}-postgis-${POSTGIS_VERSION}-scripts \
postgresql-client postgresql-contrib-${POSTGRESQL_VERSION} \
- python3-psycopg2 \
python3-setuptools \
zlib1g-dev
pip3 install behave osmium
if [ "$CC" = clang-8 ]; then sudo apt-get install -yq --no-install-suggests --no-install-recommends clang-8; fi
+ if [ "$PSYCOPG" = "2"]; then
+ sudo apt-get install -yq --no-install-suggests --no-install-recommends python3-psycopg2
+ else
+ pip3 install psycopg
+ fi
shell: bash
- name: Install Lua
=====================================
.github/workflows/ci.yml
=====================================
@@ -58,6 +58,7 @@ jobs:
POSTGRESQL_VERSION: 9.6
POSTGIS_VERSION: 2.5
BUILD_TYPE: Release
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -75,6 +76,7 @@ jobs:
POSTGRESQL_VERSION: 9.6
POSTGIS_VERSION: 2.5
BUILD_TYPE: Release
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -93,6 +95,7 @@ jobs:
POSTGRESQL_VERSION: 10
POSTGIS_VERSION: 3
BUILD_TYPE: Debug
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -111,6 +114,7 @@ jobs:
POSTGRESQL_VERSION: 11
POSTGIS_VERSION: 2.5
BUILD_TYPE: Debug
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -128,6 +132,7 @@ jobs:
POSTGRESQL_VERSION: 12
POSTGIS_VERSION: 2.5
BUILD_TYPE: Debug
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -146,6 +151,7 @@ jobs:
POSTGRESQL_VERSION: 13
POSTGIS_VERSION: 3
BUILD_TYPE: Debug
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -164,6 +170,7 @@ jobs:
POSTGIS_VERSION: 3
USE_PROJ_LIB: 6
BUILD_TYPE: Debug
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -182,6 +189,7 @@ jobs:
POSTGIS_VERSION: 3
USE_PROJ_LIB: off
BUILD_TYPE: Debug
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -200,6 +208,7 @@ jobs:
POSTGIS_VERSION: 3
USE_PROJ_LIB: 6
BUILD_TYPE: Debug
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -217,6 +226,7 @@ jobs:
POSTGRESQL_VERSION: 13
POSTGIS_VERSION: 2.5
BUILD_TYPE: Release
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -232,6 +242,7 @@ jobs:
POSTGRESQL_VERSION: 13
POSTGIS_VERSION: 2.5
BUILD_TYPE: Release
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -249,6 +260,7 @@ jobs:
POSTGRESQL_VERSION: 14
POSTGIS_VERSION: 3
BUILD_TYPE: Debug
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -267,6 +279,7 @@ jobs:
POSTGIS_VERSION: 3
USE_PROJ_LIB: 6
BUILD_TYPE: Debug
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -285,6 +298,7 @@ jobs:
POSTGIS_VERSION: 3
USE_PROJ_LIB: off
BUILD_TYPE: Debug
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -303,6 +317,7 @@ jobs:
POSTGIS_VERSION: 3
USE_PROJ_LIB: 6
BUILD_TYPE: Debug
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -321,6 +336,7 @@ jobs:
POSTGRESQL_VERSION: 14
POSTGIS_VERSION: 3
BUILD_TYPE: Release
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -337,6 +353,7 @@ jobs:
POSTGRESQL_VERSION: 14
POSTGIS_VERSION: 3
BUILD_TYPE: Release
+ PSYCOPG: 2
steps:
- uses: actions/checkout at v3
@@ -355,6 +372,7 @@ jobs:
POSTGIS_VERSION: 3
CPP_VERSION: 20
BUILD_TYPE: Debug
+ PSYCOPG: 3
steps:
- uses: actions/checkout at v3
@@ -373,6 +391,7 @@ jobs:
POSTGIS_VERSION: 3
CPP_VERSION: 20
BUILD_TYPE: Debug
+ PSYCOPG: 3
steps:
- uses: actions/checkout at v3
=====================================
CMakeLists.txt
=====================================
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.8.0)
-project(osm2pgsql VERSION 1.9.0 LANGUAGES CXX C)
+project(osm2pgsql VERSION 1.9.1 LANGUAGES CXX C)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
=====================================
docs/osm2pgsql-replication.1
=====================================
@@ -1,4 +1,4 @@
-.TH "OSM2PGSQL-REPLICATION" "1" "1.9.0" "" ""
+.TH "OSM2PGSQL-REPLICATION" "1" "1.9.1" "" ""
.SH NAME
osm2pgsql-replication \- osm2pgsql database updater
.SH SYNOPSIS
=====================================
docs/osm2pgsql.1
=====================================
@@ -1,4 +1,4 @@
-.TH "OSM2PGSQL" "1" "1.9.0" "" ""
+.TH "OSM2PGSQL" "1" "1.9.1" "" ""
.SH NAME
.PP
osm2pgsql - OpenStreetMap data to PostgreSQL converter
=====================================
scripts/osm2pgsql-replication
=====================================
@@ -122,7 +122,7 @@ class DBConnection:
host=args.host, port=args.port,
fallback_application_name="osm2pgsql-replication")
- self.name = self.conn.get_dsn_parameters()['dbname']
+ self.name = self.conn.info.dbname
def __enter__(self):
return self
=====================================
src/flex-lua-expire-output.cpp
=====================================
@@ -46,25 +46,19 @@ create_expire_output(lua_State *lua_state, std::string const &default_schema,
}
// required "maxzoom" field
- auto value = luaX_get_table_optional_uint32(
- lua_state, "maxzoom", -1, "The 'maxzoom' field in a expire output");
- if (value >= 1 && value <= 20) {
- new_expire_output.set_minzoom(value);
- new_expire_output.set_maxzoom(value);
- } else {
- throw std::runtime_error{
- "Value of 'maxzoom' field must be between 1 and 20."};
- }
+ auto const maxzoom = luaX_get_table_optional_uint32(
+ lua_state, "maxzoom", -1, "The 'maxzoom' field in a expire output", 1,
+ 20, "1 and 20");
+ new_expire_output.set_minzoom(maxzoom);
+ new_expire_output.set_maxzoom(maxzoom);
lua_pop(lua_state, 1); // "maxzoom"
// optional "minzoom" field
- value = luaX_get_table_optional_uint32(
- lua_state, "minzoom", -1, "The 'minzoom' field in a expire output");
- if (value >= 1 && value <= new_expire_output.maxzoom()) {
- new_expire_output.set_minzoom(value);
- } else if (value != 0) {
- throw std::runtime_error{
- "Value of 'minzoom' field must be between 1 and 'maxzoom'."};
+ auto const minzoom = luaX_get_table_optional_uint32(
+ lua_state, "minzoom", -1, "The 'minzoom' field in a expire output", 1,
+ maxzoom, "1 and 'maxzoom'");
+ if (minzoom > 0) {
+ new_expire_output.set_minzoom(minzoom);
}
lua_pop(lua_state, 1); // "minzoom"
=====================================
src/geom.hpp
=====================================
@@ -22,6 +22,7 @@
#include <cassert>
#include <cmath>
#include <initializer_list>
+#include <type_traits>
#include <utility>
#include <variant>
#include <vector>
@@ -197,12 +198,15 @@ public:
using iterator = typename std::vector<GEOM>::iterator;
using value_type = GEOM;
+ static constexpr bool const for_point = std::is_same_v<GEOM, point_t>;
+
[[nodiscard]] std::size_t num_geometries() const noexcept
{
return m_geometry.size();
}
- GEOM &add_geometry(GEOM &&geom)
+ GEOM &
+ add_geometry(typename std::conditional_t<for_point, point_t, GEOM &&> geom)
{
m_geometry.push_back(std::forward<GEOM>(geom));
return m_geometry.back();
=====================================
src/lua-utils.cpp
=====================================
@@ -160,7 +160,9 @@ bool luaX_get_table_bool(lua_State *lua_state, char const *key, int table_index,
}
uint32_t luaX_get_table_optional_uint32(lua_State *lua_state, char const *key,
- int table_index, char const *error_msg)
+ int table_index, char const *error_msg,
+ uint32_t min, uint32_t max,
+ char const *range)
{
assert(lua_state);
assert(key);
@@ -172,7 +174,13 @@ uint32_t luaX_get_table_optional_uint32(lua_State *lua_state, char const *key,
if (!lua_isnumber(lua_state, -1)) {
throw fmt_error("{} must contain an integer.", error_msg);
}
- return lua_tonumber(lua_state, -1);
+
+ auto const num = lua_tonumber(lua_state, -1);
+ if (num < static_cast<double>(min) || num > static_cast<double>(max)) {
+ throw fmt_error("{} must be between {}.", error_msg, range);
+ }
+
+ return static_cast<uint32_t>(num);
}
// Lua 5.1 doesn't support luaL_traceback, unless LuaJIT is used
=====================================
src/lua-utils.hpp
=====================================
@@ -58,7 +58,9 @@ char const *luaX_get_table_string(lua_State *lua_state, char const *key,
char const *default_value);
uint32_t luaX_get_table_optional_uint32(lua_State *lua_state, char const *key,
- int table_index, char const *error_msg);
+ int table_index, char const *error_msg,
+ uint32_t min, uint32_t max,
+ char const *range);
bool luaX_get_table_bool(lua_State *lua_state, char const *key, int table_index,
char const *error_msg, bool default_value);
=====================================
src/output-pgsql.cpp
=====================================
@@ -352,12 +352,12 @@ void output_pgsql_t::delete_from_output_and_expire(osmid_t id)
for (auto table : {t_line, t_poly}) {
if (m_expire.enabled()) {
- auto const results = m_tables[table]->get_wkb(id);
+ auto const results = m_tables.at(table)->get_wkb(id);
if (expire_from_result(&m_expire, results, m_expire_config) != 0) {
- m_tables[table]->delete_row(id);
+ m_tables.at(table)->delete_row(id);
}
} else {
- m_tables[table]->delete_row(id);
+ m_tables.at(table)->delete_row(id);
}
}
}
@@ -485,7 +485,7 @@ output_pgsql_t::output_pgsql_t(std::shared_ptr<middle_query_t> const &mid,
std::abort(); // should never be here
}
- m_tables[i] = std::make_unique<table_t>(
+ m_tables.at(i) = std::make_unique<table_t>(
name, type, columns, options.hstore_columns,
options.projection->target_srs(), options.append,
options.hstore_mode, copy_thread, options.output_dbschema);
@@ -504,8 +504,8 @@ output_pgsql_t::output_pgsql_t(
{
for (std::size_t i = 0; i < m_tables.size(); ++i) {
//copy constructor will just connect to the already there table
- m_tables[i] =
- std::make_unique<table_t>(*(other->m_tables[i]), copy_thread);
+ m_tables.at(i) =
+ std::make_unique<table_t>(*(other->m_tables.at(i)), copy_thread);
}
}
=====================================
src/table.hpp
=====================================
@@ -55,8 +55,6 @@ public:
pg_result_t get_wkb(osmid_t id);
- task_result_t m_task_result;
-
private:
void connect();
void prepare();
@@ -81,6 +79,7 @@ private:
columns_t m_columns;
hstores_t m_hstore_columns;
std::string m_table_space;
+ task_result_t m_task_result;
db_copy_mgr_t<db_deleter_by_id_t> m_copy;
};
=====================================
src/tagtransform-c.cpp
=====================================
@@ -7,6 +7,7 @@
* For a full list of authors see the git log.
*/
+#include <array>
#include <cstdlib>
#include <cstring>
@@ -18,27 +19,30 @@
namespace {
-const struct
+struct layers_type
{
char const *highway;
int offset;
bool roads;
-} layers[] = {{"proposed", 1, false}, {"construction", 2, false},
- {"steps", 10, false}, {"cycleway", 10, false},
- {"bridleway", 10, false}, {"footway", 10, false},
- {"path", 10, false}, {"track", 11, false},
- {"service", 15, false},
-
- {"tertiary_link", 24, false}, {"secondary_link", 25, true},
- {"primary_link", 27, true}, {"trunk_link", 28, true},
- {"motorway_link", 29, true},
-
- {"raceway", 30, false}, {"pedestrian", 31, false},
- {"living_street", 32, false}, {"road", 33, false},
- {"unclassified", 33, false}, {"residential", 33, false},
- {"tertiary", 34, false}, {"secondary", 36, true},
- {"primary", 37, true}, {"trunk", 38, true},
- {"motorway", 39, true}};
+};
+
+constexpr std::array<layers_type, 25> const layers = {
+ {{"proposed", 1, false}, {"construction", 2, false},
+ {"steps", 10, false}, {"cycleway", 10, false},
+ {"bridleway", 10, false}, {"footway", 10, false},
+ {"path", 10, false}, {"track", 11, false},
+ {"service", 15, false},
+
+ {"tertiary_link", 24, false}, {"secondary_link", 25, true},
+ {"primary_link", 27, true}, {"trunk_link", 28, true},
+ {"motorway_link", 29, true},
+
+ {"raceway", 30, false}, {"pedestrian", 31, false},
+ {"living_street", 32, false}, {"road", 33, false},
+ {"unclassified", 33, false}, {"residential", 33, false},
+ {"tertiary", 34, false}, {"secondary", 36, true},
+ {"primary", 37, true}, {"trunk", 38, true},
+ {"motorway", 39, true}}};
} // anonymous namespace
=====================================
tests/bdd/environment.py
=====================================
@@ -13,8 +13,13 @@ import io
from importlib.machinery import SourceFileLoader
from behave import *
-import psycopg2
-from psycopg2 import sql
+try:
+ import psycopg2 as psycopg
+ from psycopg2 import sql
+except ImportError:
+ import psycopg
+ from psycopg import sql
+
from steps.geometry_factory import GeometryFactory
from steps.replication_server_mock import ReplicationServerMock
@@ -44,14 +49,18 @@ def _connect_db(context, dbname):
object as a context manager that automatically closes.
Note that the connection does not commit automatically.
"""
- return closing(psycopg2.connect(dbname=dbname))
+ if psycopg.__version__.startswith('2'):
+ conn = psycopg.connect(dbname=dbname)
+ conn.autocommit = True
+ return closing(conn)
+
+ return psycopg.connect(dbname=dbname, autocommit=True)
def _drop_db(context, dbname, recreate_immediately=False):
""" Drop the database with the given name if it exists.
"""
with _connect_db(context, 'postgres') as conn:
- conn.set_isolation_level(0)
with conn.cursor() as cur:
db = sql.Identifier(dbname)
cur.execute(sql.SQL('DROP DATABASE IF EXISTS {}').format(db))
@@ -136,7 +145,6 @@ def test_db(context, **kwargs):
_drop_db(context, dbname, recreate_immediately=True)
with _connect_db(context, dbname) as conn:
- conn.autocommit = True
with conn.cursor() as cur:
cur.execute('CREATE EXTENSION postgis')
=====================================
tests/bdd/flex/lua-expire-output-definitions.feature
=====================================
@@ -104,7 +104,7 @@ Feature: Expire output definitions in Lua file
Then running osm2pgsql flex fails
And the error output contains
"""
- Value of 'maxzoom' field must be between 1 and 20.
+ The 'maxzoom' field in a expire output must be between 1 and 20.
"""
Scenario: Minzoom value in expire output definition has to be in range
@@ -121,7 +121,7 @@ Feature: Expire output definitions in Lua file
Then running osm2pgsql flex fails
And the error output contains
"""
- Value of 'minzoom' field must be between 1 and 'maxzoom'.
+ The 'minzoom' field in a expire output must be between 1 and 'maxzoom'.
"""
Scenario: Minzoom value in expire output definition has to be smaller than maxzoom
@@ -138,6 +138,6 @@ Feature: Expire output definitions in Lua file
Then running osm2pgsql flex fails
And the error output contains
"""
- Value of 'minzoom' field must be between 1 and 'maxzoom'.
+ The 'minzoom' field in a expire output must be between 1 and 'maxzoom'.
"""
=====================================
tests/bdd/steps/steps_db.py
=====================================
@@ -11,7 +11,11 @@ import math
import re
from typing import Iterable
-from psycopg2 import sql
+try:
+ from psycopg2 import sql
+except ImportError:
+ from psycopg import sql
+
@given("the database schema (?P<schema>.+)")
def create_db_schema(context, schema):
@@ -25,7 +29,7 @@ def delete_table(context, table):
cur.execute("DROP TABLE " + table)
- at then("table (?P<table>.+) has (?P<row_num>\d+) rows?(?P<has_where> with condition)?")
+ at then(r"table (?P<table>.+) has (?P<row_num>\d+) rows?(?P<has_where> with condition)?")
def db_table_row_count(context, table, row_num, has_where):
assert table_exists(context.db, table)
@@ -40,7 +44,7 @@ def db_table_row_count(context, table, row_num, has_where):
f"Table {table}: expected {row_num} rows, got {actual}"
- at then("the sum of '(?P<formula>.+)' in table (?P<table>.+) is (?P<result>\d+)(?P<has_where> with condition)?")
+ at then(r"the sum of '(?P<formula>.+)' in table (?P<table>.+) is (?P<result>\d+)(?P<has_where> with condition)?")
def db_table_sum_up(context, table, formula, result, has_where):
assert table_exists(context.db, table)
=====================================
tests/bdd/steps/steps_execute.py
=====================================
@@ -148,7 +148,7 @@ def setup_style_file(context, style):
context.osm2pgsql_params.extend(('-S', str(context.test_data_dir / style)))
- at when("running osm2pgsql (?P<output>\w+)(?: with parameters)?")
+ at when(r"running osm2pgsql (?P<output>\w+)(?: with parameters)?")
def execute_osm2pgsql_successfully(context, output):
returncode = run_osm2pgsql(context, output)
@@ -160,7 +160,7 @@ def execute_osm2pgsql_successfully(context, output):
f"Output:\n{context.osm2pgsql_outdata[0]}\n{context.osm2pgsql_outdata[1]}\n"
- at then("running osm2pgsql (?P<output>\w+)(?: with parameters)? fails")
+ at then(r"running osm2pgsql (?P<output>\w+)(?: with parameters)? fails")
def execute_osm2pgsql_with_failure(context, output):
returncode = run_osm2pgsql(context, output)
@@ -179,7 +179,7 @@ def execute_osm2pgsql_replication_successfully(context):
f"Output:\n{context.osm2pgsql_outdata[0]}\n{context.osm2pgsql_outdata[1]}\n"
- at then("running osm2pgsql-replication fails(?: with returncode (?P<expected>\d+))?")
+ at then(r"running osm2pgsql-replication fails(?: with returncode (?P<expected>\d+))?")
def execute_osm2pgsql_replication_successfully(context, expected):
returncode = run_osm2pgsql_replication(context)
@@ -190,7 +190,7 @@ def execute_osm2pgsql_replication_successfully(context, expected):
f"Output:\n{context.osm2pgsql_outdata[0]}\n{context.osm2pgsql_outdata[1]}\n"
- at then("the (?P<kind>\w+) output contains")
+ at then(r"the (?P<kind>\w+) output contains")
def check_program_output(context, kind):
if kind == 'error':
s = context.osm2pgsql_outdata[1]
=====================================
tests/common-import.hpp
=====================================
@@ -70,7 +70,7 @@ public:
data_t() = default;
template <typename CONTAINER>
- data_t(CONTAINER const &objects)
+ explicit data_t(CONTAINER const &objects)
{
std::copy(std::begin(objects), std::end(objects),
std::back_inserter(m_objects));
@@ -167,7 +167,8 @@ public:
void run_import(options_t options, char const *data,
std::string const &format = "opl")
{
- run_import(options, std::initializer_list<std::string>{data}, format);
+ run_import(std::move(options), std::initializer_list<std::string>{data},
+ format);
}
void run_file(options_t options, char const *file = nullptr)
@@ -195,7 +196,7 @@ public:
testing::pg::conn_t connect() { return m_db.connect(); }
- testing::pg::tempdb_t const &db() const { return m_db; }
+ testing::pg::tempdb_t const &db() const noexcept { return m_db; }
private:
testing::pg::tempdb_t m_db;
=====================================
tests/test-expire-from-geometry.cpp
=====================================
@@ -332,22 +332,22 @@ TEST_CASE("expire multipoint geometry", "[NoDB]")
expire_config_t const expire_config;
expire_tiles et{zoom, defproj};
- geom::point_t p1{0.0, 0.0};
- geom::point_t p2{15000.0, 15000.0};
+ geom::point_t const p1{0.0, 0.0};
+ geom::point_t const p2{15000.0, 15000.0};
SECTION("multipoint")
{
geom::multipoint_t mpt;
- mpt.add_geometry(std::move(p1));
- mpt.add_geometry(std::move(p2));
+ mpt.add_geometry(p1);
+ mpt.add_geometry(p2);
et.from_geometry(mpt, expire_config);
}
SECTION("geom")
{
geom::multipoint_t mpt;
- mpt.add_geometry(std::move(p1));
- mpt.add_geometry(std::move(p2));
+ mpt.add_geometry(p1);
+ mpt.add_geometry(p2);
geom::geometry_t const geom{std::move(mpt)};
et.from_geometry(geom, expire_config);
}
@@ -355,8 +355,8 @@ TEST_CASE("expire multipoint geometry", "[NoDB]")
SECTION("geom with check")
{
geom::multipoint_t mpt;
- mpt.add_geometry(std::move(p1));
- mpt.add_geometry(std::move(p2));
+ mpt.add_geometry(p1);
+ mpt.add_geometry(p2);
geom::geometry_t geom{std::move(mpt)};
geom.set_srid(3857);
et.from_geometry_if_3857(geom, expire_config);
=====================================
tests/test-output-pgsql-z_order.cpp
=====================================
@@ -33,7 +33,7 @@ TEST_CASE("compute Z order")
" ORDER BY z_order DESC"
" LIMIT 1 OFFSET {}",
i);
- REQUIRE(expected[i] == conn.result_as_string(sql));
+ REQUIRE(expected.at(i) == conn.result_as_string(sql));
}
REQUIRE("residential" ==
View it on GitLab: https://salsa.debian.org/debian-gis-team/osm2pgsql/-/commit/25898b2b0594c3eb0e885df3dc4b08057d975a90
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/osm2pgsql/-/commit/25898b2b0594c3eb0e885df3dc4b08057d975a90
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20230823/c9403b5d/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list