Skip to content

Instantly share code, notes, and snippets.

@typebrook
Last active February 25, 2023 11:32
Show Gist options
  • Select an option

  • Save typebrook/d166d5e8d0a293c30f697b0f403b3c0e to your computer and use it in GitHub Desktop.

Select an option

Save typebrook/d166d5e8d0a293c30f697b0f403b3c0e to your computer and use it in GitHub Desktop.
A simple script to upload OsmChange file #osm #changeset #script

Upload OsmChange file with script

Usage

# By default, changeset would be uploaded to test server: 
# https://master.apis.dev.openstreetmap.org
./osm.api.changeset.commit <OSC FILE>

# Use --serious to upload changeset to normal OSM server
./osm.api.changeset.commit --serious <OSC FILE>

# STDIN would be treated as comment, or a prompt shows up
echo "This is changeset comment" | ./osm.api.changeset.commit <OSC FILE>

# Set env OSM_USER_PASSWD as the following format, to skip prompt input:
# <USER>:<PASSWORD>
OSM_USER_PASSWD=<USER>:<PASSWORD> osm.api.changeset.commit <OSC FILE>

# Set env CHANGESET with the id of a open changeset
# Then script will not create a new changeset
# Instead, use existing one to upload OSC file and close it
CHANGESET=<ID_OF_CHANGESET> ./osm.api.changeset.commit <OSC FILE>

# Alternative way with online script
curl -fsS https://raw.githubusercontent.com/typebrook/helper/dev/bin/osm/osm.api.changeset.commit | \
bash /dev/stdin <OSC FILE>

# For development, use bats for testing:
# https://bats-core.readthedocs.io/
./test.bats
#!/bin/sh
set -e
OSM_SERVER=https://api.openstreetmap.org
OSM_TEST_SERVER=https://master.apis.dev.openstreetmap.org
# Commit to test server unless --serious is given
if echo "$@" | grep -q '\--serious' ; then
SERVER=$OSM_SERVER
else
SERVER=$OSM_TEST_SERVER
fi
OSM_API=${SERVER}/api/0.6
FILE="$(echo "$@" | sed s/--serious//)"
# Fail if no OSC file is given
if [ -z "$FILE" ]; then
echo No OSC file is given >&2
exit 1
fi
# Prompt for comment and User:Password
if [ ! -t 0 ]; then
comment=$(cat)
else
echo -n 'Type comment: '
read -r comment </dev/tty
fi
if [ -z "${OSM_USER_PASSWD}" ]; then
echo -n 'Type USER:PASSWD: '
read -r OSM_USER_PASSWD </dev/tty
fi
# API call for changeset create
# If env SOURCE is set, add it as part of changeset:
# <tag k='source' v='$SOURCE'/>
create_changeset() {
SOURCE_TAG="${SOURCE:+$(printf "<tag k='source' v='%s'/>" $SOURCE)}"
# Create changeset with given information
response="$(curl ${OSM_API}/changeset/create \
--fail-with-body \
--user "$OSM_USER_PASSWD" \
--upload-file - \
--silent \
<<' EOF'
<osm>
<changeset>
${SOURCE_TAG}
<tag k='comment' v='${comment}'/>
<tag k='created_by' v='bash script'/>
<tag k='bot' v='yes'/>
</changeset>
</osm>
EOF
)" || local result=fail
# If return code >200, or the response is not a sequence number
# Exit with return code 1
if [ "$result" = fail ] || ! echo "$response" | grep -qE '^[[:digit:]]+$' ; then
echo
echo Fail to create a new changeset: >&2
echo "$response" >&2
return 1
else
changeset_id=$response
fi
}
# API call for uploading OSC file
uploade_file_to_changeset() {
response="$(curl -X POST $OSM_API/changeset/$1/upload \
--fail-with-body \
--user "$OSM_USER_PASSWD" \
--upload-file - \
--silent
)" || local result=fail
if [ "$result" = fail ]; then
echo
echo Fail to upload OSC file: >&2
echo "$response" >&2
return 1
fi
}
# API call for closing changeset
close_changeset() {
response="$(curl -X PUT ${OSM_API}/changeset/$1/close \
--fail-with-body \
--user "$OSM_USER_PASSWD" \
--silent
)" || local result=fail
if [ "$result" = fail ]; then
echo
echo Fail to close changeset: >&2
echo "$response" >&2
return 1
fi
}
# Create changeset when CHANGESET is not set
if [ -z $CHANGESET ]; then
echo 'CHANGESET is not set, create a new one'
create_changeset && \
echo "Changeset created, check ${SERVER}/changeset/${changeset_id}" || \
exit 1
else
echo "CHANGESET is set, use ${CHANGESET} as changeset ID"
changeset_id=$CHANGESET
fi
# Upload OSC file to Changeset
sed -Ee "/<(node|way|relation)/ s/>/ changeset=\"${changeset_id}\">/" $FILE |\
uploade_file_to_changeset ${changeset_id} && \
echo Upload file $FILE to changeset ${changeset_id} || \
exit 1
# Close Changeset
close_changeset ${changeset_id} && \
echo Changeset ${changeset_id} closed || \
exit 1
#! /bin/bats --verbose-run
export OSM_USER_PASSWD=
setup() {
# Create OSC file for each test
cat <<' OSC' >test.osc
<osmChange version="0.6" generator="bash script">
<create>
<node id="-1" version="1" lat="24" lon="121">
</node>
</create>
</osmChange>
OSC
}
teardown() {
rm test.osc
}
check_passwd() {
if [[ -z $OSM_USER_PASSWD ]]; then
skip 'Please set env OSM_USER_PASSWD in .bats file'
fi
}
print_oputput() {
echo -e "${output}" | sed 's/^/\t/' >&3
}
@test "POSIX compatible" {
run checkbashisms -f ./osm.api.changeset.commit
[ "$status" -eq 0 ]
print_oputput
}
@test "Fail with zero augument" {
run ./osm.api.changeset.commit
[ "$status" -eq 1 ]
[[ "$output" =~ 'No OSC file is given' ]]
print_oputput
}
@test "Fail with invalid user/passwd" {
run sh -c 'echo "test comment" | OSM_USER_PASSWD=foo:bar ./osm.api.changeset.commit test.osc'
[ "$status" -eq 1 ]
[[ "$output" =~ 'Fail to create a new changeset:' ]]
print_oputput
}
@test "Fail with invalid OSC file" {
check_passwd
run sh -c 'echo "test comment" | ./osm.api.changeset.commit <(echo "Some random file content")'
[[ "$output" =~ 'Changeset created' ]]
[[ "$output" =~ 'Fail to upload OSC file:' ]]
[ "$status" -eq 1 ]
print_oputput
}
@test "Create changeset" {
check_passwd
run sh -c 'echo "test comment" | ./osm.api.changeset.commit test.osc'
[[ "$output" =~ 'Changeset created' ]]
[ "$status" -eq 0 ]
print_oputput
}
@typebrook
Copy link
Author

@jidanni I think now it is POSIX compatible, bats is introduced for testing.

Screenshot_2023-02-25-16-25-26_1920x1080

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment