Merge pull request #1143 from matthiasbeyer/doc

Doc
This commit is contained in:
Matthias Beyer 2017-10-15 18:40:22 +02:00 committed by GitHub
commit 212ff3945e
7 changed files with 203 additions and 148 deletions

View File

@ -2,13 +2,21 @@
This document is the user documentation for imag, the personal
information management suite for the commandline. Besides beeing a documentation,
it servey also as "roadmap" where this project should go. Parts which are not
yet implemented might be documented already, therefore. A list on what is
implemented and what is not can be found at the end of this document.
it serves also as "roadmap" where this project should go. Parts which are not
yet implemented might be documented already, therefore. Also, because this is a
hobby thing, parts which are implemented might be documented falsely or not at
all.
A list on what is implemented and what is not can be found at the end of this
document.
It might be outdated though.
**Basically: This is Hobby stuff. Expect incompleteness, false statements and
generally read with big grain of salt.**
If you have any objections, suggestions for improvements, bugs, etc, please file
them. A way to reach out to the imag project maintainer(s) is described in the
CONTRIBUTING file of the repository or in this document, on the appropriate
them.
A way to reach out to the imag project maintainer(s) is described in the
CONTRIBUTING file of the repository or in this document, on the appropriate
section.
## The Problem {#sec:intro:problem}
@ -28,6 +36,9 @@ date, but that _all things_ can be linked together. For example that a wiki
article can be linked to a date which is linked to a todo which is linked to a
note which is linked to a contact.
Also, having an all-in-one scriptable modular commandline personal information
management suite seemed nice at the time and still does.
## The Approach {#sec:intro:approach}
The approach "imag" takes on solving this problem is to store content in a

View File

@ -1,23 +1,41 @@
# Architecture of the imag code
The imag codebase has a rather simple overall architecture. But before introducing the reader to it, a few things have to be introduced.
The imag codebase has a rather simple overall architecture.
In this chapter the types of crates, architecture of an imag module
and the type structure are described.
## Crate types
There are different types of crates in the imag world. A crate is a rust project.
There are different types of crates in the imag world. A crate is a rust
project.
First of all, there are core crates. These crates provide the very core of imag and almost all other crates use them:
First of all, there are core crates. These crates provide the very core of imag
and almost all other crates use them:
* libimagstore - The imag store is the abstraction overbthe filesystem. It provides primitives to get, write and manipulate store entries and their header information.
* libimagrt - The runtime library, which provides functionality to create a store object from libimagstore, helps with configurarion loading and commandline argument handling (through the external "clap" crate).
* libimagerror - Error handling library for handling errors the imag way. Used in all other crates, even the store itself. It also offers functionality to log and trace errors as well as exiting the application, if necessary.
* libimagstore - The imag store is the abstraction over the filesystem. It
provides primitives to get, write and manipulate store entries and their
header information.
* libimagrt - The runtime library, which provides functionality to create a
store object from libimagstore, helps with configurarion loading and
commandline argument handling (through the external "clap" crate).
* libimagerror - Error handling library for handling errors the imag way. Used
in all other crates, even the store itself. It also offers functionality to
log and trace errors as well as exiting the application, if necessary.
* libimagutil - Utilities.
The next type of imag crates are entry extension libraries. Those provide extensional functionality for the types from libimagstore. For example, there is "libimagentrylink" which provides functionality to link two entries in the store.
The next type of imag crates are entry extension libraries. Those provide
extensional functionality for the types from libimagstore. For example, there is
"libimagentrylink" which provides functionality to link two entries in the
store.
The next kind of crate is the one that offers end-user functionality for a imag aspect, for example "libimagtodo" provides functionality to track todos.
The third kind of crate is the one that offers end-user functionality for a imag
domain, for example "libimagtodo" provides functionality to track todos.
And last, but not least, the commandline frontend crates provide the user interface. These are the kind of crates that are not library crates, but binaries.
And last, but not least, the commandline frontend crates provide the user
interface. These are the kind of crates that are not library crates, but
binaries.
Besides these, there are some other utility crates.
## Architecture of an imag module
@ -47,22 +65,47 @@ With the things from above, a module could have the following architecture:
+-----------------------------------+---------+
```
The foundation of all imag modules is the store, as one can see from the image. Above this there is the libimagrt, which provides the basic runtime and access to the `Store` object. Cross-cutting, there is the error library (and possibly the util library, but we do not care about this one here), which is used through all levels. The highest level of all imag modules is the commandline interface on top of the domain library.
In between can be any number of entry extension libraries, or none if not needed.
The foundation of all imag modules is the store, as one can see in the image.
Above the store library there is the libimagrt, which provides the basic runtime
and access to the `Store` object.
Cross-cutting, there is the error library (and possibly
the util library, but we do not care about this one here), which is used through
all levels. The highest level of all imag modules is the commandline interface
on top of the domain library. In between can be any number of entry extension
libraries, or none if not needed.
Theoretically, the commandline interface crate could be replaced to build a
terminal user interface, graphical user interface or web interface.
## Types
The imag core, hence the libimagstore, libimagrt and libimagerror, provide a set of types that a user (as in a library writer) should be aware of.
The imag core, hence the libimagstore, libimagrt and libimagerror, provide a set
of types that a user (as in a library writer) should be aware of.
First of all, there is the Runtime type which is provided by the libimagrt. It provides basic access to whether debugging or verbosity is enabled as well as the most important core object: The `Store`.
First of all, there is the `Runtime` type which is provided by the libimagrt. It
provides basic access to whether debugging or verbosity is enabled as well as
the most important core object: The `Store`.
It is provided by the libimagstore library, the heart of everything.
The `Store` type is provided by the libimagstore library, the heart of
everything.
When interacting with the store, two types are visible: `FileLockEntry` and `Entry` whereas the former derefs to the latter, which basically means that the former wraps the latter.
The `FileLockEntry` is a necessary wrapper for ensuring that when working concurrently with the store, an entry is only _borrowed_ once from the store. It also ensures that the object is alive as long as the store is.
When interacting with the store, two types are visible: `FileLockEntry` and
`Entry` whereas the former derefs to the latter, which basically means that the
former wraps the latter. The `FileLockEntry` is a necessary wrapper for
ensuring that when working concurrently with the store, an entry is only
_borrowed_ once from the store. It also ensures that the object is alive as long
as the store is.
The `Entry` type provides functionality like reading the actual content, its header and so on. Extensions for its functionality are implemented on this type, not on the `FileLockEntry`.
The `Entry` type provides functionality like reading the actual content, its
header and so on. Extensions for its functionality are implemented on this type,
not on the `FileLockEntry`.
The `Entry` provides access to its header, which is a `toml::Value`, where toml is the toml-rs crate (external project). Conveniance functionality is provided via the `toml-query` crate, which is an external project which was initiated and extracted from the imag project.
The `Entry` provides access to its header, which is a `toml::Value`, where toml
is the toml-rs crate (external project). Convenience functionality is provided
via the `toml-query` crate, which is an external project which was initiated and
extracted from the imag project.
Error types are also important. All errors in the imag prijects are generated by libimagerror usage and are interoperable. User code hardly handles the actual `Error` type but its inner one, `ErrorKind`, which is an enum where each member can be mapped to a representing text. Imag error types do never contain payload (they can via extensions, though it is not really practical and there is no usage for it).
Error types are also important.
All errors in imag projects should be created with `error-chain`.
libimagerror provides functionality to enhance the experience with `Result`
types and general tracing of errors.

View File

@ -4,13 +4,19 @@ The store is where all the good things happen.
The store is basically just a directory on the filesystem imag manages and keeps
its state in.
One could say that the store is simply a databases, and it really is. We opted
One could say that the store is simply a database, and it really is. We opted
to go for plain text, though, as we believe that plain text is the only sane way
to do such a thing.
to do such a thing, especially because the amount of data which is to be
expected in this domain is in the lower Megabytes range and even if it is
_really_ much won't exceed the Gigabytes ever.
Having a storage format which is plain-text based is the superior approach, as
text editors will always be there.
A user should always be able to read her data without great effort and putting
everything in a _real_ database like sqlite or even postgresql would need a user
to install additional software just to read his own data. We don't want that.
Text is readable until the worlds end and we think it is therefor better to
Text is readable until the worlds end and we think it is therefore better to
store the data in plain text.
The following sections describe the store and the file format we use to store
@ -19,10 +25,10 @@ to dig into the store with their editors.
## File Format {#sec:thestore:fileformat}
The contents of the store are encoded in either UTF-8 or ASCII. Either way, a
normal text editor (like `vim` or the other one) will always be sufficient to
dog into the store and modify files. For simple viewing even a pager (like
`less`) is sufficient.
The contents of the store are encoded in UTF-8.
A normal text editor (like `vim` or the other one) will always be sufficient to
dig into the store and modify files.
For simple viewing even a pager (like `less`) is sufficient.
Each entry in the store consists of two parts:
@ -44,24 +50,24 @@ restricted in their way of altering the data.
So normally there are several sections in the header. One section (`[imag]`) is
always present. It contains a `version` field, which tells imag which version
this file was created with (the version information is _also_ encoded in the
filename, just in case things change in the future). It also contains a `links`
field which is an Array of values. This `links` field is for linking (see
@sec:thestore:linking) to other entries in the store.
this file was created with.
Other sections are named like the modules which created them. Every module is
allowed to store arbitrary data under its own section and a module may never
read other sections than its own. This is not enforced by imag itself, though.
read other sections than its own.
These conventions are not enforced by imag itself, though.
### Content Format {#sec:thestore:fileformat:content}
The content is the part of the file where the user is free to enter any textual
content. The content may be rendered as Markdown or other markup format for the
users convenience. The store does never expect and specific markup and actually
the markup implementation is not inside the very code of imag.
the markup implementation is not inside the very core of imag.
Technically it would be possible that the content part of a file is used to
store binary data. We don't want this, though.
store binary data.
We don't want this, though, as it is contrary to the goals of imag.
### Example {#sec:thestore:fileformat:example}
@ -88,7 +94,7 @@ This is an example text, written by the user.
The "Entries" are stored as files in the "Store", which is a directory the
user has access to. The store may exist in the users Home-directory or any
other directory the user has read-write-Access to.
other directory the user has read-write-access to.
Each module stores its data in an own subdirectory in the store. This is because
we like to keep things ordered and clean, not because it is technically
@ -100,54 +106,23 @@ So if the store exists in `/home/user/store/`, a file with the storepath
`/example.file` is (on the filesystem) located at
`/home/user/store/example.file`.
A storepath contains predefined parts:
By convention, each `libimagentry<name>` and `libimag<name>` module stores its
entries in in `/<name>/`.
* The module name of the Module the Entry belongs to, as said above.
This part is always a directory.
* The version (semantic versioning applies) of the module storing the entry.
This part is a postfix to the filename.
The pattern for the storepath is
So, the pattern for the storepath is
```
/<module name>/<optional sub-folders>/<file name>~<sem version>
/<module name>/<optional sub-folders>/<file name>
```
So if a module named "example-module" with version "0.1.0" stores a file in the
Store, the storepath for a file with the name "example" is
"/example-module/example~0.1.0".
Any number of subdirectories may be used, so creating folder hierarchies is
possible and valid. A file "example" for a module "module" in version "0.1.0"
would be stored in sub-folders like this:
possible and valid.
A file "example" for a module "module" could be stored in sub-folders like this:
```
/module/some/sub/folder/example~0.1.0
/module/some/sub/folder/example
```
For example, it is valid if these files exist at the same time:
* /foo/bar~0.2
* /foo/bar~1.3
It might not be sane, though.
To future-proof the system it is necessary to provide a way for modules to
differentiate in their versions on the store level. Thus if a module wants to
retrieve a file from the store it must at least accept files from it's current
advertised version. It may accept older files and it may transform them and
resubmit them in the newer version.
## Store path links {#sec:thestore:links}
Linking entries is version independent.
This means if an entry "a" from a module "A" gets written to the store, it may
link to an entry "b" from a module "B", which is in version "0.1.0" at the
moment. If the module "B" gets updated, it might update its entries in the store
as well. The link from the "a" should never get invalid in this case, though it
is not ensured by the core of imag itself.
## Backends {#sec:thestore:backends}
The store itself also has a backend. This backend is the "filesystem
@ -158,21 +133,21 @@ Note: This is a very core thing. Casual users might want to skip this section.
### Problem {#sec:thestore:backends:problem}
First, we had a compiletime backend for the store.
This means that the actual filesystem operations were compiled into the stores
This means that the actual filesystem operations were compiled into the store
either as real filesystem operations (in a normal debug or release build) but as
a in-memory variant in the 'test' case.
So tests did not hit the filesystem when running.
This gave us us the possibility to run tests concurrently with multiple stores
that did not interfere with eachother.
that did not interfere with each other.
This approach worked perfectly well until we started to test not the
store itself but crates that depend on the store implementation.
When running tests in a crate that depends on the store, the store
itself was compiled with the filesystem-hitting-backend.
This was problematic, as tests could not be implemented without hitting
the filesystem.
the filesystem and mess up other currently-running tests.
Hence we implemented this.
Hence we implemented store backends.
### Implementation {#sec:thestore:backends:implementation}
@ -213,7 +188,7 @@ backend in other ways, too.
This is a backend for the imag store which is created
from stdin, by piping contents into the store (via JSON or TOML) and piping the
store contents (as JSON or TOML) to stdout when the the backend is destructed.
store contents (as JSON or TOML) to stdout when the backend is destructed.
This is one of some components which make command-chaining in imag possible.
With this, the application does not have to know whether the store actually
@ -227,12 +202,8 @@ implementation are possible.
The following section assumes a JSON mapper.
The mapper reads the JSON, parses it (thanks serde!) and translates it to
a `Entry`, which is the in-memory representation of the files.
The `Entry` contains a `Header` part and a `Content` part.
This is then made available to the store codebase.
The mapper reads the JSON, parses it and translates it to a `Entry`.
Then, the entry is made available to the store codebase.
To summarize what we do right now, lets have a look at the awesome ascii-art
below:
@ -243,9 +214,7 @@ below:
IO Mapper Store Mapper IO
+--+---------+----------------+--------+--+
| | | | | |
JSON -> Entry -> JSON
+ Header
+ Content
JSON -> Entry -> JSON
```
This is what gets translated where for one imag call with a stdio store backend.

View File

@ -1,58 +1,104 @@
# Conventions, best practices
This section goes about best practices in the imag codebase. It is mainly focused on developers, but a user may read it for getting to know how imag works.
This section goes about best practices in the imag codebase. It is mainly
focused on developers, but a user may read it for getting to know how imag
works.
Lets work our way up from the store and how to extend it to the commandline user interface.
Lets work our way up from the store and how to extend it to the commandline user
interface.
## Versioning
All imag crates are versioned with the same version number until we reach some
`"1.0.0"` version.
This means that all imag tools are only tested for compatibility with libraries
and such if their version numbers match.
It might not be possible to import one imag library in version 0.3.0 and another
one in 0.4.0 and make them work together.
It also means that if new tools are introduced into the imag codebase, they
might start with their first version not at 0.1.0 but at something like 0.5.0.
## Store and Entry functionality
A `Entry` does not offer much functionality by itself. So its the job of libraries to _extend_ their functionality. This should never be done by wrapping the `Entry` type itself but by providing and implementing an extension trait on it.
A `Entry` does not offer much functionality by itself. So its the job of
libraries to _extend_ its functionality. This should never be done by wrapping
the `Entry` type itself but by providing and implementing an extension trait on
it.
Same goes for extending the `Store` type: never wrap it, always provide an extension trait for it.
Same goes for extending the `Store` type: never wrap it, always provide an
extension trait for it.
These two rules ensure that the type does not lose any functionality from a wrapping. `Deref` could do that, but not over muliple levels, so extension traits it is. It also most likely results in functions inside the extension trait which all return a `Result<_, _>`.
These two rules ensure that the type does not lose any functionality from a
wrapping. `Deref` could do that, but not over muliple levels, so extension
traits it is. It also most likely results in functions inside the extension
trait which all return a `Result<_, _>`.
## Libraries
In the next few sections, conventions and best practices for writing a imag library are written down.
In the next few sections, conventions and best practices for writing a imag
library are written down.
A developer of imag should read this carefully, a user may skip this section or cross-read it for better understanding of the imag project.
A developer of imag should read this carefully, a user may skip this section or
cross-read it for better understanding of the imag project.
### Library naming
Libraries which provide functionality for entries or the store (most likely entries or both) should be named "libimagentrything" whereas "thing" stands for what the library provides.
Libraries which provide functionality for entries or the store (most likely
entries or both) should be named "libimagentrything" whereas "thing" stands for
what the library provides.
All other libraries should be prefixed with "libimag" at least. Most likely, one will not write such a library but rather a "libimagentrything" library.
All other libraries should be prefixed with "libimag" at least. Most likely, one
will not write such a library but rather a "libimagentrything" library.
### Library scope
A library should never introduce utility functionality which could be useful for other libraries as well. If there is no such functionality available, the "libimagutil" might be a place where such a function would be put, or, if not yet available, a "libimagentryutil" could be created.
A library should never introduce utility functionality which could be useful for
other libraries as well. If there is no such functionality available, the
"libimagutil" might be a place where such a function would be put, or, if not
yet available, a "libimagentryutil" could be created.
If a library has to introduce free functions in its public interface, one should think hard whether this is really necessary.
If a library has to introduce free functions in its public interface, one should
think hard whether this is really necessary.
### Library error types/kinds
Libraries must use the "libimagerror" tools to create error types and kinds. Most likely, a library needs some kinds for wrapping the errors from underlying libraries, such as the store itself.
Libraries must use the "libimagerror" tools to create error types and kinds.
Most likely, a library needs some kinds for wrapping the errors from underlying
libraries, such as the store itself.
A library must _never_ introduce multiple error types, but is free to introduce as many error kinds as required. Indeed, more kinds is better than fewer.
A library must _never_ introduce multiple error types, but is free to introduce
as many error kinds as required. Indeed, more kinds is better than fewer.
### Libraries with commandline frontends
Libraries with commandline frontends provide end-user functionality. Normally, they depend on one or more "libimagentrything" libraries. They should be named "libimagthing", though. For example: "libimagdiary", "libimagtimetrack" or "libimagwiki", whereas the commandline frontends would be "imag-diary", "imag-timetrack" and "imag-wiki", respectively.
Libraries with commandline frontends provide end-user functionality. Normally,
they depend on one or more "libimagentrything" libraries. They should be named
"libimagthing", though. For example: "libimagdiary", "libimagtimetrack" or
"libimagwiki", whereas the commandline frontends would be "imag-diary",
"imag-timetrack" and "imag-wiki", respectively.
If such a library needs to depend on another "libimagthing", for example if "libimagdiary" needs to depend on "libimagnote", one should think about this and whether the functionality could ve outsourced to a more general "libimagentrything". It is not forbidden, though.
If such a library needs to depend on another "libimagthing", for example if
"libimagdiary" needs to depend on "libimagnote", one should think about this and
whether the functionality could be outsourced to a more general
"libimagentrything". It is not forbidden, though.
A library which implements a functionality for imag may contain helper functions for commandline stuff, but that is discouraged.
A library which implements a functionality for imag may contain helper functions
for commandline stuff, but that is discouraged.
### Library testing
All libraries should be tested as much as possible. Sometimes it may not be possible without a lot of effort, but still: more tests = better!
All libraries should be tested as much as possible. Sometimes it may not be
possible without a lot of effort, but still: more tests = better!
## Commandline tools
The next few sections describe how the commandline frontends are implemented. Each imag functionality (or module) has its own library and a commandline frontend for it.
The next few sections describe how the commandline frontends are implemented.
Each imag functionality (or module) has its own library and a commandline
frontend for it.
The commandline frontends do contain little to no functionality. They simply translate the commandline parameters and options to calls to the appropriate library functions.
The commandline frontends do contain little to no functionality. They simply
translate the commandline parameters and options to calls to the appropriate
library functions.
## Commandline tool testing

View File

@ -6,36 +6,13 @@ There is a huge list of modules available in the imag core distribution.
From a naming perspective, we do not differ between low-level and high-level
modules. Some of the modules shipped with imag cover core functionality such as
linking, tagging or references to files outside of the store or even the store
interface itself (which by the way shouldn't be used by the end-user at all).
interface itself.
Others cover things like diary, notes, wiki or bookmarks.
These are also called "domains".
We try really hard to offer a consistent commandline user interface over all of
these modules.
The following sections describe each module in detail, including its purpose and
its provided backends.
A backend is simply an external tool imag might be able to use.
For example, the `imag-todo` module offers a `taskwarrior` interface, so imag
itself does not cover anything which has to do with todo management, but lets
you continue using `taskwarrior` for that (which does a really good job).
So what does the `imag-todo` module do?
Well, it offers you ways to track tasks created in `taskwarrior` and putting
files which can be used as references to tasks then.
For example, if you create a task in `taskwarrior`, you end up with an UUID for
this task.
imag stores this UUID in a store entry and you are now able to `imag-link` this
file with other files in the store.
This way you can link `taskwarrior` tasks with other data (of course,
`imag-todo` offers some more commands, for searching tasks and so on).
But what if you do not like `taskwarrior`?
That's what backends are for.
The goal of imag is to provide backends for not just one tool which implements a
PIM aspect, but for many.
So you can change the configuration for `imag-todo` to not use `taskwarrior` but
some other todo tool.
(This is all hypothetical by now because these things are not yet implemented.
Anyhow, we aim for exactly what is described above)
its provided functionality.

View File

@ -11,9 +11,12 @@ short note what each module should do.
First the modules which have been implemented in some way (not necessarily
perfect or feature-complete):
- [x] imag-annotate - A helper for quickly annotating entries in the store
- [x] imag-bookmark - A bookmark manager for web browsing.
- [x] imag-counter - Counting things.
- [x] imag-diary - A diary, or multiple.
- [x] imag-gps - Adding GPS coordinates to entries
- [x] imag-grep - A helper to grep through the store (not entry headers)
- [x] imag-grep - A utility for greping through content
- [x] imag-link - Linking imag entries to eachother
- [x] imag-notes - Note taking
@ -37,7 +40,6 @@ Now the modules that are not yet started:
based on a predicate specified via the CLI and write the store back to stdout.
- [ ] imag-git - wrapper to call git commands on the imag store no matter
whether the current working directory is the store or not
- [ ] imag-gps - Adding GPS coordinates to entries
- [ ] imag-habit - Tracking ones habits (create habits and make sure you do what
you've planned)
- [ ] imag-image - Image referencing, categorizing, etc.

View File

@ -11,16 +11,17 @@ section](#prerequisites). If you don't know what you could do, start here.
## Without Github
If you do not want to use github for your contribution, this is completely okay.
Contributing without a github account is perfectly fine.
Feel free to contact [us via our mailinglist](http://imag-pim.org/mailinglist/)
via mail, feel also free to submit patches via mail (use `git format-patch` and
and/or submit patches via mail (use `git format-patch` and
`git send-email`, always add a cover letter to describe your submission).
Also ensure that each commit has
[a "Signed-off-by: " line](https://stackoverflow.com/questions/1962094/what-is-the-sign-off-feature-in-git-for).
By adding that line, you agree to our
[developer certificate of origin](#developer-certificate-of-origin).
If you do not add the "Signed-off-by: " line, I cannot take your patch, sorry.
If you do not add the "Signed-off-by: " line,
I reserve the right to reject your patch.
Once _I am_ okay with your patchset, I will
submit it as PR in the github repository, so more people can review it and CI
@ -36,6 +37,8 @@ Finding an issue is simple: We have
[a special label in our issues section](https://github.com/matthiasbeyer/imag/issues?q=is%3Aissue+is%3Aopen+label%3Acomplexity%2Feasy)
for easy-to-solve issues. You can start there, don't hesitate to ask questions
if you do not understand the issue comment!
If there are currently no issues with that tag, just browse the issues or the
code... you'll always find things to improve!
Also, if you've found bugs or outdated stuff in our documentation, feel free to
file issues about them or even better: Write a pull request to fix them!
@ -48,8 +51,6 @@ Dependencies are listed in the
[default.nix file](http://git.imag-pim.org/imag/tree/default.nix),
though you do not have to have `nix` installed to build imag.
`make` can be helpful to automate the build process.
Note that this software is targeted towards commandline linux users and we do
not aim to be portable to Windows or Mac OSX (though I wouldn't mind merging
patches for OS X compatibility).
@ -70,11 +71,15 @@ All dependencies are installable with the nix package manager by using a
Please don't refer to issues or PRs from inside a commit message, if possible.
Make sure your PR does not contain "Fixup" commits when publishing it, but feel
free to push "Fixup" commits in the review process. We will ask you to clean
your history before merging! If you're submitting via patch-mail, I will do the fixup squashing myself.
your history before merging! If you're submitting via patch-mail, I will do the
fixup squashing myself.
Make sure to prefix your commits with `"doc: "` if you change the document. Do
not change document and code in one commit, always separate them.
If your changes are user-visible, make sure to add a note in the
`CHANGELOG.md` file.
We do not follow some official Rust styleguide for our codebase, but we try to
write minimal and readable code. 100 characters per line, as few lines as
possible, avoid noise in the codebase, ... you get it.
@ -93,9 +98,9 @@ for example "libimagstore/add-debugging-calls", that would be awesome.
You are welcome to publish your PR as soon as there is one commit in your
branch. This gives us the possibility to review whether your ideas go into a
nice direction or whether there are issues with your approach and we can report
them to you rather quickly. Rewriting a whole PR is not satisfactory and we'd
like to make your contribution process enjoyable.
nice direction or whether there are issues with your approach so we can report
them to you quickly. Rewriting a whole PR is not satisfactory and we'd
like to make your contribution process enjoyable for you.
# Merging tools which use the imag core functionality into this repo
@ -107,12 +112,14 @@ requirements:
1. It has a commandline interface which is the main interface to the module
OR it is a utility library for creating new kinds of functionality within the
imag core.
The commandline interface should be structured like the existing interfaces
(as in commands, options and arguments).
1. It is licensed under the terms of GNU LGPLv2.1 OR all of your contributors
approve a commit which changes the license of your codebase to GNU LGPLv2.1
(The word "approve" in this sentence is to be defined).
(If your tool does not fulfill these requirements, I won't merge it into the
imag core distribution.)
If your tool does not fulfill these requirements, I won't merge it into the
imag core distribution.
## Code of Conduct