Merge pull request #1457 from matthiasbeyer/minor

Minor
This commit is contained in:
Matthias Beyer 2018-05-02 11:41:30 +02:00 committed by GitHub
commit c4d10c7e4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 250 additions and 17 deletions

View file

@ -68,6 +68,48 @@ install-directory is in your `$PATH`), or install the `imag` binary to call `ima
<modulename>` (also if everything is in your `$PATH`). <modulename>` (also if everything is in your `$PATH`).
## Example usage
As imag is a big and complex project, we cannot show all tools of the suite
here. But to give you some idea, here's an example:
```bash
# Lets initialize imag
imag init
# Recursively import vcf files
imag contact import /home/user/contacts
# Create a contact (vcf) in the private collection
imag contact create --file /home/user/contacts/private
# Add a diary entry
imag diary -p private create
# Uh, I forgot something in a diary entry, select one and edit it
# use the `fzf` tool here (not a part of imag) to select from the IDs
imag diary -p private list | fzf -m | imag edit -I
# Link a contact to the diary entry
imag link diary/private/2018/01/01/00:00:00 contact/bc222298-casf-40a4-bda1-50aa980a68c9
# Annotate a contact with some notes
imag annotate add contact/bc222298-casf-40a4-bda1-50aa980a68c9 contact-notes
# Write down some notes named "pineapple"
imag notes create "pineapple"
# Where was that contact again?
imag grep Eva
# Okay, we need to add some imag-internal notes to that contact
imag grep Eva -l | imag edit -I
# Now save our work
imag git add . # "imag-git" simply calls git in the imag store
imag git commit -m 'Commit message'
```
## Staying up-to-date ## Staying up-to-date
We have a [official website for imag](https://imag-pim.org), where I post We have a [official website for imag](https://imag-pim.org), where I post

View file

@ -3,7 +3,7 @@ name = "imag-mv"
version = "0.8.0" version = "0.8.0"
authors = ["Matthias Beyer <mail@beyermatthias.de>"] authors = ["Matthias Beyer <mail@beyermatthias.de>"]
description = "Part of the imag core distribution: imag command" description = "Part of the imag core distribution: imag-mv command"
keywords = ["imag", "PIM", "personal", "information", "management"] keywords = ["imag", "PIM", "personal", "information", "management"]
readme = "../../../README.md" readme = "../../../README.md"

View file

@ -22,6 +22,20 @@ This section contains the changelog from the last release to the next release.
* Minor changes * Minor changes
* Bugfixes * Bugfixes
## 0.7.1
Bugfix release for fixing:
* `libimagdiary` did not return the youngest, but the oldest entry id on `::get_youngest_entry_id()`.
* `imag-view` should not always wrap the text, only if -w is passed
* `imag-log show` should order by date
* `imag` does not inherit stdout if detecting imag command versions.
* `imag-contact import` does only allow absolute pathes
* `imag-contact` has most fields optional now, only name is required
* `imag-contact` automatically creates UID
* `imag-contact` automatically generates/warns about missing file extension
## 0.7.0 ## 0.7.0
* Major changes * Major changes

View file

@ -0,0 +1,23 @@
#!/usr/bin/env bash
#
# A helper script for the mutt query_command
#
# Use
#
# query_command = "/path/to/this/script %s"
#
# in mutt to search contacts from mutt with imag.
#
# mutt wants a one-line status message before the list of contacts.
echo "Searching with imag ..."
imag contact find "$1" --json | \
jq --raw-output '
map(.fullname[0] as $FN
| .email
| map({email: ., fullname: $FN}))
| flatten
| map([.email.address, .fullname, .email.properties.TYPE])
| .[]
| @tsv
'

View file

@ -0,0 +1,152 @@
#!/usr/bin/env bash
#
# This script imports iOverlander data into a imag-wiki
#
# Requirements
# ============
#
# * imag-wiki
# * imag-gps
# * imag-store
# * jq
#
# Usage
# =====
#
# Download the JSON data files from app.ioverlander.com and run them through
# this script.
#
# ./this/script wiki-name ioverlander-file.json
#
# What it does
# ============
#
# It imports each location from the JSON data into one entry at:
#
# <wiki_name>/<country>/<location name>_<location id>
#
# (The location id is added because names are sometimes reused)
#
# * It uses imag-gps to set the GPS data
# * It sets the header of the entry to the data it finds from the JSON object.
# It puts all data in the "userdata.ioverlander" namespace.
# It strips whitespace from the keys.
# It ignores the GPS data from the JSON object though, as this was added via
# imag-gps.
# * It uses the "description" field as entry content.
#
# Warning
# =======
#
# As the ioverlander data sometimes contains "/" in the name, some entries are
# namespaced. This has to be fixed and the linkings have to be adapted. This is
# not yet handled by this script.
#
#
WIKI_NAME="$1"
IOVERLANDER_FILE_PATH="$2"
[[ -z "$WIKI_NAME" ]] && echo "Wiki name missing" && exit 1
[[ -z "$IOVERLANDER_FILE_PATH" ]] && echo "JSON file missing" && exit 1
imag wiki create-wiki "$WIKI_NAME" --no-edit
echo "Created imag wiki '$WIKI_NAME'"
tobool() {
if [[ "$1" == "Yes" ]]; then
echo "true"
elif [[ "$1" == "No" ]]; then
echo "false"
else
echo "\"$1\""
fi
}
object_to_vars() {
jq -r -c 'to_entries | .[] | .key + "=\"" + (.value | tostring | gsub("\\\""; "")) + "\""'
}
# The comments in this function can be outcommented for debugging
process_object() {
read -r json
local location_latitude
local location_longitude
local location_altitude
local location_horizontal_accuracy
local location_vertical_accuracy
local amenities_Open
local amenities_Electricity
local amenities_Wifi
local amenities_Kitchen
local amenities_Restaurant
local amenities_Showers
local amenities_Water
local amenities_Toilets
local amenities_Big_rig_friendly
local amenities_Tent_friendly
local amenities_Pet_friendly
local id
local name
local description
local date_verified
local category_icon_path
local category_icon_pin_path
local country
local category
#echo "----------------------------------------------------------"
#echo "JSON = $json"
#echo "-----------"
#echo $json | jq '.location' | object_to_vars | sed 's,^,location_,'
#echo $json | jq '.amenities' | object_to_vars | sed 's,^,amenities_,; s, Big,_big,; s, Rig,_rig,; s, Friendly,_friendly,'
#echo $json | jq 'del(.location)|del(.amenities)' | object_to_vars
eval $(echo $json | jq '.location' | object_to_vars | sed 's,^,location_,')
eval $(echo $json | jq '.amenities' | object_to_vars | sed 's,^,amenities_,; s, Big,_big,; s, Rig,_rig,; s, Friendly,_friendly,')
eval $(echo $json | jq 'del(.location)|del(.amenities)' | object_to_vars)
local ctry_slug=$(echo $country | sed 's, ,_,g')
local name_slug=$(echo $name | sed 's, ,_,g')
echo "create = $ctry_slug/${name_slug}_${id}"
local article=$(imag wiki --wiki "$WIKI_NAME" create "$ctry_slug/${name_slug}_${id}" --no-edit --print-id || exit 1)
echo "ARTICLE = $article"
imag gps add --lat="$location_latitude" --long="$location_longitude" "$article" || {
echo "GPS setting failed"
exit 1
}
imag store update --id "$article" \
--header \
"userdata.ioverlander.id=\"$id\"" \
"userdata.ioverlander.name=\"$name\"" \
"userdata.ioverlander.date_verified=\"$date_verified\"" \
"userdata.ioverlander.country=\"$country\"" \
"userdata.ioverlander.category=\"$category\"" \
"userdata.ioverlander.amenities.open=$(tobool "$amenities_Open")" \
"userdata.ioverlander.amenities.electricity=$(tobool "$amenities_Electricity")" \
"userdata.ioverlander.amenities.wifi=$(tobool "$amenities_Wifi")" \
"userdata.ioverlander.amenities.kitchen=$(tobool "$amenities_Kitchen")" \
"userdata.ioverlander.amenities.restaurant=$(tobool "$amenities_Restaurant")" \
"userdata.ioverlander.amenities.showers=$(tobool "$amenities_Showers")" \
"userdata.ioverlander.amenities.water=$(tobool "$amenities_Water")" \
"userdata.ioverlander.amenities.toilets=$(tobool "$amenities_Toilets")" \
"userdata.ioverlander.amenities.big_rig_friendly=$(tobool "$amenities_Big_rig_friendly")" \
"userdata.ioverlander.amenities.tent_friendly=$(tobool "$amenities_Tent_friendly")" \
"userdata.ioverlander.amenities.pet_friendly=$(tobool "$amenities_Pet_friendly")" \
--content \""$description\"" || {
echo "header/content setting failed";
exit 1
}
}
cat "$IOVERLANDER_FILE_PATH" | jq -c '.[]' | while read line; do
process_object
done

View file

@ -96,6 +96,7 @@ impl FileAbstractionInstance for FSFileAbstractionInstance {
}; };
*self = FSFileAbstractionInstance::File(file, path); *self = FSFileAbstractionInstance::File(file, path);
if let FSFileAbstractionInstance::File(ref mut f, _) = *self { if let FSFileAbstractionInstance::File(ref mut f, _) = *self {
trace!("Writing buffer...");
return f.write_all(&buf).chain_err(|| SEK::FileNotWritten); return f.write_all(&buf).chain_err(|| SEK::FileNotWritten);
} }
unreachable!(); unreachable!();
@ -186,9 +187,12 @@ fn open_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
fn create_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> { fn create_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
if let Some(parent) = p.as_ref().parent() { if let Some(parent) = p.as_ref().parent() {
debug!("Implicitely creating directory: {:?}", parent); trace!("'{}' is directory = {}", parent.display(), parent.is_dir());
if let Err(e) = create_dir_all(parent) { if !parent.is_dir() {
return Err(e); trace!("Implicitely creating directory: {:?}", parent);
if let Err(e) = create_dir_all(parent) {
return Err(e);
}
} }
} }
OpenOptions::new().write(true).read(true).create(true).open(p) OpenOptions::new().write(true).read(true).create(true).open(p)

View file

@ -177,6 +177,7 @@ impl StoreEntry {
fn write_entry(&mut self, entry: &Entry) -> Result<()> { fn write_entry(&mut self, entry: &Entry) -> Result<()> {
if self.is_borrowed() { if self.is_borrowed() {
assert_eq!(self.id, entry.location); assert_eq!(self.id, entry.location);
trace!("Writing entry...");
self.file self.file
.write_file_content(entry) .write_file_content(entry)
.map(|_| ()) .map(|_| ())
@ -442,11 +443,13 @@ impl Store {
debug!("Writing Entry"); debug!("Writing Entry");
se.write_entry(&entry.entry)?; se.write_entry(&entry.entry)?;
trace!("Entry written");
if modify_presence { if modify_presence {
debug!("Modifying presence of {} -> Present", entry.get_location()); debug!("Modifying presence of {} -> Present", entry.get_location());
se.status = StoreEntryStatus::Present; se.status = StoreEntryStatus::Present;
} }
trace!("Entry updated successfully");
Ok(()) Ok(())
} }
@ -798,6 +801,7 @@ impl<'a> Drop for FileLockEntry<'a> {
use libimagerror::trace::trace_error_dbg; use libimagerror::trace::trace_error_dbg;
trace!("Dropping: {:?} - from FileLockEntry::drop()", self.get_location()); trace!("Dropping: {:?} - from FileLockEntry::drop()", self.get_location());
if let Err(e) = self.store._update(self, true) { if let Err(e) = self.store._update(self, true) {
trace!("Error happened in FileLockEntry::drop() while Store::update()ing");
trace_error_dbg(&e); trace_error_dbg(&e);
if_cfg_panic!("ERROR WHILE DROPPING: {:?}", e); if_cfg_panic!("ERROR WHILE DROPPING: {:?}", e);
} }

View file

@ -388,6 +388,8 @@ pub mod iter {
impl InternalLinker for Entry { impl InternalLinker for Entry {
fn get_internal_links(&self) -> Result<LinkIter> { fn get_internal_links(&self) -> Result<LinkIter> {
debug!("Getting internal links");
trace!("Getting internal links from header of '{}' = {:?}", self.get_location(), self.get_header());
let res = self let res = self
.get_header() .get_header()
.read("links.internal") .read("links.internal")
@ -400,6 +402,8 @@ impl InternalLinker for Entry {
fn set_internal_links(&mut self, links: Vec<&mut Entry>) -> Result<LinkIter> { fn set_internal_links(&mut self, links: Vec<&mut Entry>) -> Result<LinkIter> {
use internal::iter::IntoValues; use internal::iter::IntoValues;
debug!("Setting internal links");
let self_location = self.get_location().clone(); let self_location = self.get_location().clone();
let mut new_links = vec![]; let mut new_links = vec![];
@ -430,11 +434,13 @@ impl InternalLinker for Entry {
} }
fn add_internal_link(&mut self, link: &mut Entry) -> Result<()> { fn add_internal_link(&mut self, link: &mut Entry) -> Result<()> {
debug!("Adding internal link: {:?}", link);
let location = link.get_location().clone().into(); let location = link.get_location().clone().into();
add_internal_link_with_instance(self, link, location) add_internal_link_with_instance(self, link, location)
} }
fn remove_internal_link(&mut self, link: &mut Entry) -> Result<()> { fn remove_internal_link(&mut self, link: &mut Entry) -> Result<()> {
debug!("Removing internal link: {:?}", link);
let own_loc = self.get_location().clone().without_base(); let own_loc = self.get_location().clone().without_base();
let other_loc = link.get_location().clone().without_base(); let other_loc = link.get_location().clone().without_base();

View file

@ -1,12 +0,0 @@
#!/usr/bin/env bash
if [[ -z "$1" ]]; then
echo "No rev list given"
exit 1
fi
for rev in $(git rev-list $1); do
if git notes --ref=changelog list $rev &> /dev/null; then
git log -n 1 --show-notes=* --pretty="format:* %N" $rev
fi
done

View file

@ -10,7 +10,7 @@ fi
for rev in $(git rev-list "$since"..HEAD | tac); do for rev in $(git rev-list "$since"..HEAD | tac); do
if git notes --ref=changelog list $rev &> /dev/null; then if git notes --ref=changelog list $rev &> /dev/null; then
output=$(git notes --ref=changelog show $rev | sed '2,$s/^/ /') output=$(git notes --ref=changelog show $rev | sed '2,$s/^/ /')
echo "* $output" echo "* [$(echo ${rev:0:10})] $output"
fi fi
done done