Git Product home page Git Product logo

git-pile's Introduction

git-pile

Manage a pile of patches on top of a git branch

Requirements

  • Python >= 3.7
  • git >= 2.20
  • Python modules:
    • argcomplete (optional for shell completion)
    • coverage (optional for tests)

Quickstart

Running git-pile

git-pile follows the git naming convention for binaries so we can use it as a subcommand to git. Either of the following forms work if the git-pile is in the search PATH:

$ git pile -h
$ git-pile -h

For autocomplete to work you need Python's argcomplete module installed. In the first case, you also need to source the bash autocomplete file extra/git-pile-complete.sh so git knows how to complete the subcommand.

You can also install git-pile as a python package, although that's still not recommended since it's being updated frequently.

$ ./setup.py install

OR

$ ./setup.py install --user

In case a --user option is provided to the command above it will install under $HOME directory and bash completion file will be at $XDG_DATA_HOME/git-pile/bash_completion. There isn't a standard user directory for bash completion we can install to, so the user is expected to source this file.

Repository initialization

Initialize a new empty pile:

$ git pile init

Now you have a (orphan) pile branch to keep track of patch files to be managed on top of the master branch. Branch names may be changed via options to git pile init. Like git init creates a new repository, git pile init will create a new pile.

Alternatively, if the pile branch already exists in a remote repository (or even locally) and you want to setup your work tree to use it you should use the command below:

$ git pile setup internal/pile internal/embargo-branch

In the example above we have a remote called internal which has a branch named pile that contains the patch files and a branch named embargo-branch that will be the branch being generated when we apply the patches.

The second argument is optional and if not given the current branch will be used.

Develop a new commit and send to mailing list

You can use your normal git flow to develop changes in the project and create commits. Here is an example that is by no means restricted to git-pile:

$ git checkout -b newfeature internal/embargo-branch
$ echo "platform 16" >> platforms.txt
$ git add platforms.txt
$ git commit "add new platform"

Continuing from the initialization example, we create a new branch with internal/embargo-branch as the base. The result can be prepared to send to a mailing list in the same vein as how git format-patch works:

$ git pile format-patch -o /tmp/patches
/tmp/patches/0000-cover-letter.patch
/tmp/patches/0001-add-new-platform.patch

The cover letter will contain the diff to the pile branch (with patches added and so on), while the patch files will also be available in isolation: those are diffs to the result branch, and present to ease review.

If the commit you are adding should not be on top, but rather in the middle of the long running patch series, you can just move it down in the tree with git rebase -i. In the example below we will move it 10 commits down:

$ git rebase -i -11

  [ editor opens and you move the commit around. You can also reorder
    commits, edit commit message, etc, etc. Anything you do in an
    interactive rebase you can do here ]

$ git pile format-patch -o /tmp/patches
/tmp/patches/0000-cover-letter.patch
/tmp/patches/0001-old-platform.patch
/tmp/patches/0002-old-platform-2.patch
/tmp/patches/0003-add-new-platform.patch

Any patch that needs to be changed in order to accommodate the patch in the middle of the series will be prepared by git pile format-patch.

Generate the pile from the changed tree

Instead of sending to the mailing list, you can simply transform the changes from the branch to the physical patches maintained in the pile branch.

$ git pile genpatches master..newfeature
$ cd patches
$ git add -A
$ git commit -m "add platform"
$ git pile genbranch

This generates the patches, saving the final state in the patch series, and then recreates embargo-branch locally. Patches may be reordered, added in the middle, reworded etc. By going through the genpatches + genbranch cycle we can always re-generate the branch and keep the history of what was done, i.e. maintain the history of how the patches were changed/added/removed.

Apply a patch series to the pile

The cover-letter in a git-pile generated patch series (i.e. the one generated by git pile format-patch) always contain the diff of the original state of the tree to the current state. It may be used to apply the entire series by targeting the patches directory instead of the normal working directory.

$ # machine 2
$ cd pile
$ git am /tmp/patches/0000-cover-letter.patch
$ git genbranch

This will apply the entire series that was received (even if it was a 10 patches series, only the specially-formatted cover-letter needs to be applied).

Destroying the pile

If anything goes wrong and you'd like to start over, you can call the destroy command. This will remove all configuration saved by git-pile, the pile branch itself and the worktree directory it was using. If you have a backup of the patches (either manual or if the pile branch is in a remote repository), this is pretty safe to do and allows you to redo the configuration.

git-pile's People

Contributors

adrinael avatar ashutoshx avatar cmarcelo avatar dbstimson avatar dceraolo avatar dragoonaethis avatar guludo avatar jausmus avatar jnikula avatar lucasdemarchi avatar mattrope avatar rodrigovivi avatar saiteja13427 avatar zehortigoza avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

git-pile's Issues

Support one pile per git worktree

We already have use cases with multiple worktrees within a single repo and we would like to have a pile in each such worktree. Appears this is not currently supported. Currently (v1.1) the last pile created becomes the only pile and overwrites the previous pile in a different worktree. .git/config only shows a single pile, the last one created.

Creating this issue to support one pile per worktree, so that git pile commands (reset, format-patch, genbranch) can be run from multiple worktrees transparently.

Allow testing git-pile with different versions of git

We support git>=2.19. However it is possible that a contributor has a more recent version of git and could add code that is not backward-compatible with our supported version. An example is #87, which used an option for git ls-tree that was only available as of version 2.36 of git.

While it is fairly easy to download git's source, compile it and run the tests using PATH="path/to/git/version/2.19/bin:$PATH" bats test, it would be nice if we had something in our test infra-structure that made it easier to test with different git versions. Then, we could enable tests with git 2.19 and also with the latest stable release by default.

Some options in this direction:

  1. There is a tool created specifically for managing versions of tools, called asdf. It seems adding a plugin for git and using it here would not be that difficult.
  2. Another option would be adding a home-made script that would download and and compile the two git versions for us.
  3. Investigate using github action configuration to select the correct git version. That would make things not so easy to run tests locally, though.

In cases (1) and (2), we could then have a script that invoked the tests with each git version.

git pile genlinear-branch fails

[igt-gpu-tools]$ git pile genlinear-branch -b internal-linear
Traceback (most recent call last):
  File "/home/adixit/.local/bin/git-pile", line 4, in <module>
    __import__('pkg_resources').run_script('git-pile==1.0.dev0', 'git-pile')
  File "/usr/lib/python3.10/site-packages/pkg_resources/__init__.py", line 656, in run_script
    self.require(requires)[0].run_script(script_name, ns)
  File "/usr/lib/python3.10/site-packages/pkg_resources/__init__.py", line 1453, in run_script
    exec(code, namespace, namespace)
  File "/home/adixit/.local/lib/python3.10/site-packages/git_pile-1.0.dev0-py3.10.egg/EGG-INFO/scripts/git-pile", line 12, in <module>
    sys.exit(git_pile.main(*sys.argv[1:]))
  File "/home/adixit/.local/lib/python3.10/site-packages/git_pile-1.0.dev0-py3.10.egg/git_pile/git_pile.py", line 2432, in main
    return args.func(args, config)
  File "/home/adixit/.local/lib/python3.10/site-packages/git_pile-1.0.dev0-py3.10.egg/git_pile/git_pile.py", line 1698, in cmd_genlinear_branch
    parent_ref, pile_range = get_refs_from_linearized(args.incremental, config.pile_branch, args.start_ref, branch, notes_ref)
  File "/home/adixit/.local/lib/python3.10/site-packages/git_pile-1.0.dev0-py3.10.egg/git_pile/git_pile.py", line 1660, in get_refs_from_linearized
    return None, pile_range
UnboundLocalError: local variable 'pile_range' referenced before assignment

Add config for temporary worktree

Allow the user to specify in the configuration a temporary worktree to be used by git-pile in all operations that need a temporary worktree. This would allow genbranch without --inplace to gain most of the speedup as well since it doesn't need to create a temporary worktree there, just reset a checkout that is probably near to what we are resetting to.

This also allows the user to solve conflicts in genbranch if he is not using --inplace

3e3abbc ("am: check pile-commit is available on remote") breaks an important use case

The commit message for 3e3abbc says:

    Then if we forget to do `git -C patches reset --hard HEAD^`, the next
    `git pile format-patch` will be the diff between v1 and v2, not the diff
    between the current (remote) state of the pile and v2.

However, if I have multiple patchsets in flight, I may actually want to generate cover letters which are diff between the patchset 1 and patchset 2 (that is for each patchset individually, not an aggregate diff between patchset2 and the current state of the pile). This use case is broken by 3e3abbc.

Is this expected 'git pile format-patch --local' behavior?

I have an extra local pile commit and the corresponding results branch (output of genbranch including the extra pile commit).

When I do a 'git pile format-patch --local' with this, git pile correctly says there are no new changes.

Now I add some patches on top of the results branch. When I again do 'git pile format-patch --local' I only expected to see the patches on top in the cover letter. However, the cover letter is showing all previous changes corresponding to the previous extra pile commit too in the cover letter. Is this expected? Thanks.

Support .git outside work-tree

Some people prefer to have a bare repo outside and add worktrees on the side. One way to accomplish that is like this in the playground repo:

git clone --bare https://github.com/git-pile/playground.git
cd playground.git
git worktree add ../playground internal

When we do this we will have the following setup:

$ git worktree list
/tmp/playground.git  (bare)
/tmp/playground      b6f49eb [internal]

Since git-pile uses the concept of "git_root" or "main checkout", this doesn't work very well since in this scenario there is no such thing: there is the bare repo and each worktree is one storing its data in playground.git/worktrees.

Stop warning about non-patch files to increase compatibility with CI

CI runners like to add a dot directory/file where the configuration is kept. In a pile-based workflow, the pile branch is the natural place to keep them. Example: with "github actions" that would be the .github directory.

We may just ignore any file/dir starting with a dot if that works.

git pile format-patch cover letters are unreliable

Every once is a while (though this is fairly rare) we hit a situation where a 'git pile am -g' with a cover letter generated with 'git pile format-patch' results in a branch which is different from the original branch used to generate the cover letter.

As we know 'git pile format-patch' cover letters are generated using 'git range-diff' which has its own algorithm for determining that patches are identical and actually takes a --creation-factor argument for the algorithm.

One instance we have seen this happen is when a patch was identical to what it was previously except for a change in line numbers due to large amount of code deletion in the file (which was part of a different patch). Therefore 'git range-diff' considered this patch as unchanged and consequenty the patch was applied in the wrong place in the file during 'git am' during 'git pile genbranch'.

So that is one example where a 'git range-diff' based git pile cover letter yields erroneous results. I am not sure if there are multiple such instances where we see this issue due to the use of git range-diff (e.g. if the diff produced during 'git range-diff' has similar issues or is that always the same as the output of a regular diff).

Apart from different final and original branches I believe in some rare cases cover letters have also led to git pile genbranch failures because the patches were updated incorrectly and therefore could not be applied.

I am creating this issue to see if anything can be done about this. Ideas include:

  • Use git range-diff to only include the "metadata" in the cover letter, but include the actual diff of the patches which allows the patches to always be reconstructed accurately. Whether this causes other problems like git am conflicts or very large cover letters with say a lot of line number diff's in the patches remains to be seen.

  • Actually iterate: Follow the 'git pile format-patch' with 'git pile am -g' with the generated cover letter and make sure the output branch is the same as the original branch we started with and continue the process till this happens.

Also not sure if passing --creation-factor argument to 'git pile format-patch' helps in such situations and this is enough to address such situations.

Investigate patch creation from the range-diff

Creating the cover letter patch from the diff between the current pile and the result branch only works if the user keeps the pile and result branch in sync.

This is a very common mistake since users forget to keep them sync'ed, sometimes updating just one or the other.

For a long time now we started using the output of git-range-diff in the cover letter to aid reviewing. We should probably think about a way to use the range-diff to handcraft the patch without relying on the users' pile branch.

Teach format-patch to add only new patches

Sometimes it's good to have a way to tell git-pile format-patch to include only the new patches as "standalone emails". The interdiff and overall diff is already sent so there is no information lost. This is particularly important when adding a patch to the bottom of a branch creates a bunch of conflicts and ends up touch hundreds of patches.

It may be just a command line option, or we could use a (configurable) threshold with number of patches changed.

Commands can't be called from pile checkout on > 1.0

Since the move to consider the pile checkout always relative to the main checkout, we can't call commands from inside the the patches/ directory (or pile checkout if you will). That is because all the commands will simply append "/{pile.dir}" and then fail with a backtrace.

I was looking at a quick fix, but it became worse due to the addition of worktree config. The result from git config --get-regexp 'pile\..*' may be incorrect as the worktree config is always from the "result-branch" checkout and the checkout for the pile branch will simply return the values for the local config, not worktree.

Fix is a bit more involved, but seems possible: we need to check the worktree list output and figure out if we are in the pile checkout or result-branch checkout. Prior to even creating a Config object.

Introduce 'git pile show tree-diff' command

I think it would be useful to easily see the tree-diff corresponding to a particular pile commit, that is the diff for the result branch corresponding to a particular pile commit.

For a pile commit X, the tree-diff would be the diff between the outputs of 'git pile genbranch X~' and 'git pile genbranch X'.

am: add simple fuzzy option

Add a fuzzy git apply as fallback for am: if it failed, try: guess conflict resolution for hunk numbers. In general the conflicts are only because the line numbers changed. By just taking one or the other we can guess the resolution and rely on #3 to complete it. Guessing the resolution for hunk numbers would be:

sed -i '/^<<<<<<< HEAD/ {N;N;N;N; s/<<<<<<< HEAD.*\n@@.*\n=======.*\n\(@@.*\)\n>>>>>>>.*/\1/g}' $i

... for every patch that conflicted. After that, check if we still have any conflict markers.

Add --continue to genbranch

Reasons:

  1. So people don't need to care that we use git-am behind the scene
  2. We can tweak git index so it continues to be fast on big repos

Provide more context in full tree diff subject

From @ashutoshx:

Today the full tree diff subject line mostly says "[REVIEW] Full tree diff against internal/internal". Some more context is indirectly present because the emails are generally part of a single email thread so one can glean which thread the full tree diff is part of. However with a lot of full tree diffs present this can get confusing and providing some more context can improve things.

Perhaps we can change the subject to something like "[REVIEW] Full tree diff for *** BLURB HERE ***"

The user is supposed to replace *** BLURB HERE *** with the blurb used for generating the cover letter. This would provide more context for the full tree diff and make easier to associate the full tree diff with the correct patch series. Note that because the cover letter subject has to be entered by the user and that is also most likely the blurb to be used for the full tree diff, git pile cannot pre-generate the full tree diff subject and has to rely on the user to enter the subject.

Strategies for pruning genbranch cache

With the merge of #87, we should add a way of pruning the cache from time to time. Currently, the user has the only option of removing the cache file entirely, which is not ideal.

Points to consider:

  • Auto-pruning: Pruning should be triggered automatically when a certain condition is reached. What should the condition evaluate? Off the top of my head, I see: number of nodes of the trees or size of the cache file.
  • Pruning strategy: We need a way of deciding which nodes should be removed from the cache. An easy strategy could be to keep only nodes associated to the last k pile commits.

Add automation for branch linearization

Suppose we go through each rev of the pile branch, calling git pile genbranch -i. Each generated head is then linked to form a branch. This would basically be the "linearization" of the history, allowing us to view the "overall diff" between one commit and another.

This should be very helpful for bisect and to find what really changed between each rev.

git pile output has escape sequences without terminal

When using git pile without terminal, the output has extra control characters: eg.

‣�[0;1;39m Entering 'patches' directory �[0m

Standard is to not use any escape sequences when the terminal is missing or unknown type.

am: add fuzzy tool integration option

Besides #4, it may be possible to integrate with additional tools to solve conflicts. One example of that tool is wiggle.

git pile am --fuzzy=internal
or
git pile am --fuzzy

would use the "internal" handling.

git pile am --fuzzy=wiggle

would use our wrapper around wiggle

git pile am --fuzzy=/my/awesome/tool

would exec tool with pre-defined arguments. It should also be possible to fallback to each tool once one of them fails:

git pile am --fuzzy=internal,wiggle,/my/awesome/tool

Add automation for github integration

git-pile can be integrated in github using github actions. The idea is that pushes to the pile branch causes the result branch to be updated (or at least checked for correctness).

By providing the workflow necessary in github actions it makes easier for projects using git-pile to adopt the action without having to rewrite everything.

Consider the full tree diff as a regular numbered patch

Currently the full tree diff generated by git pile is not considered a regular patch. It is tagged [REVIEW] and patch numbering included with the cover letter does not include the full tree diff patch. This causes tools like Patchwork to ignore the full tree diff patch. In reality code review often happens directly on the full tree diff and because Patchwork ignores the full tree diff patch it also doesn't capture the code review happening on the full tree diff.

To fix this the proposal is to include the full tree diff as a regular numbered patch along with the cover letter.

Add subcommand to start a new series

One of the struggles people have using git-pile is because we a) need 2 branches in sync and b) need the original ref used to start a patch series.

Proposal here is to have a new command so people can start new patch series and have the necessary info recorded by git-pile. I think the info could be recorded in the branch description (see git-branch --edit-description). Then other git-pile subcommands like format-patch would first look at the branch description to check if it has the necessary info. Commands like genbranch should probably be changed to update the info there.

Example workflow:

(internal) $ git pile reset
(internal) $ git pile new-series my-awesome-feature
(my-awesome-feature) $ ...

Other tools have similar "start a topic / series" approach. See b4 and git-series.

genbranch: add fuzzy option

Add a fuzzy git apply for genbranch: if genbranch fails, try this:

  1. git am --show-current-patch | git apply --recount --reject --index. Give a warning in the end for patches that needed to be applied with fuzzy option. I've very good success with that approach lately
  2. git am --show-current-patch | patch -p1.

am: allow us to add signed-off-by and reviewed-by before generating the branch and patches

With the current workflow, you have to use git-pile am to apply the patch from the series, then you have to change the patches to add your r-b and/or s-o-b tags, and then you have to regenerate the branch again because you touched the patches (or you'll have to regenerate the patches because you amended commits).

We could make git-pile am launch $EDITOR for each modified patch so we could add the relevant tags while git-pile am is generating the branch in the first time. This way we' d avoid the extra branch generation, and we'd also ensure people using git-pile am don't forget to actually add their s-o-b and r-b tags to the patches.

am: exits with success if patch already applied

With non-pile am, if patches are already applied, it always exits with a non-zero exit code.

If a cover letter is already applied in the tree, git pile am behaves like this:

‣ Entering 'patches' directory
Applying: Testcase series
Using index info to reconstruct a base tree...
M       series
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.

And exit code is 0.

This doesn't happen too often, because other conflicts usually creep up to hide this problem, but sometimes pile-using CI is just happily passing along post-merge commits as a pre-merge test round because scripting doesn't notice.

Easy reproduction steps for both normal am and pile am:

  1. Make a patch
  2. [pile] am it
  3. [pile] am it again

Support multiple piles (per worktree?)

Recent git (I think >= 2.25) supports per-worktree configuration by turning on git config extensions.worktreeConfig true. In order to support multiple piles (think one pile for each branch), it would be a matter of turning this on and have the different configurations per checkout.

If that doesn't work we probably have a bug in git pile. As this is not something we use, we probably do.

Investigate integration with PRs in github

In order to make it possible to use git-pile with services like github actions / gitlab-ci, we probably need something developed in git-pile to make it possible.

Right now we depend on the cover-letter in order to apply a patch. That is not possible with github/gitlab, but there's probably an easy replacement: in the PR description, the only thing we would need is the pile-commit the developer used to create that patch series. We can recreate the series/apply by simply doing a git pile format-patch base...head where base is the result "branch" on pile-commit, head is the head the user is trying to merge and pile branch is checkout at pile-commit.

End result would be that for sending a PR the user wouldn't even need to play with git-pile, since that is automated on the server side. Except that we still need to ask what is the pile-commit.

On git-pile development side, we could have git pile mr / git pile pr that would take care of creating the pr/mr giving the developer the information needed.

color handling broke piping to git pile am

Trying to pipe a patch to git pile am:

Traceback (most recent call last):
  File "/path/to/bin/git-pile", line 12, in <module>
    sys.exit(git_pile.main(*sys.argv[1:]))
  File "/path/to/src/git-pile/git_pile/git_pile.py", line 2027, in main
    return args.func(args)
  File "/path/to/src/git-pile/git_pile/git_pile.py", line 981, in cmd_am
    info("Entering '%s' directory" % config.dir)
  File "/path/to/src/git-pile/git_pile/helpers.py", line 127, in info
    print_color(color, "‣", s, *args, **kwargs)
  File "/path/to/src/git-pile/git_pile/helpers.py", line 121, in print_color
    sl = [ color + prefix, s, *args, COLOR_RESET ]
TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'

Bisect result:

80e5f05b578cb14ae8ed083dcdf6441c137ce5b9 is the first bad commit
commit 80e5f05b578cb14ae8ed083dcdf6441c137ce5b9
Author: Lucas De Marchi <[email protected]>
Date:   Tue Mar 15 09:29:42 2022 -0700

    helpers: improve color handling in logs
    
    Add some color definitions and use yellow for warnings.
    
    Signed-off-by: Lucas De Marchi <[email protected]>

 git_pile/helpers.py | 34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)


Extra pile checks for format-patch

One common mistake is to start preparing a patch series and before finishing it do a git fetch. When this is done the RESULT_BRANCH in the remote may not match the one the feature/fix started from. When we do a git pile format-patch it implicitly uses the remote branch to compare with git range-diff. That range-diff will not make sense if it contains changes outside what we really changed.

One idea to cope with that is: assuming pile_branch and result_branch from the remote are always in sync (i.e. nobody is pushing result_branch but rather generating from it), check if the merge-base of pile and origin/pile is origin/pile. If it is something else, it means the branches diverged and we should instruct the user to use the longer form of format-patch, passing a sensible result_branch for comparison.

pip installation stopped working on python 3.11 for debian-based distros

Output on Ubuntu 23.04:

$ pip3 install --user git-pile                                                                                                                                                                                                                                                                                                                                                      
error: externally-managed-environment                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                         
× This environment is externally managed                                                                                                                                                                                                                                                                                                                                                                                                 
╰─> To install Python packages system-wide, try apt install                                                                                                                                                                                                                                                                                                                                                                              
    python3-xyz, where xyz is the package you are trying to                                                                                                                                                                                                                                                                                                                                                                              
    install.                                                                                                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                                                                                                         
    If you wish to install a non-Debian-packaged Python package,                                                                                                                                                                                                                                                                                                                                                                         
    create a virtual environment using python3 -m venv path/to/venv.                                                                                                                                                                                                                                                                                                                                                                     
    Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make                                                                                                                                                                                                                                                                                                                                                                      
    sure you have python3-full installed.                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                         
    If you wish to install a non-Debian packaged Python application,                                                                                                                                                                                                                                                                                                                                                                     
    it may be easiest to use pipx install xyz, which will manage a                                                                                                                                                                                                                                                                                                                                                                       
    virtual environment for you. Make sure you have pipx installed.                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                         
    See /usr/share/doc/python3.11/README.venv for more information.                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                         
note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages. 

format-patch: add --creation-factor support

By default git-range-diff uses "creation-factor=60%". Now we only send added patches, but we use git-range-diff's output to determine if a patch is added or modified. If user had a unexpected output, it may be good to tweak that value according to GIT-RANGE-DIFF(1).

[BUG]Pile parsing failed, if any line in the description starts with word "From"

I have encountered a situation where executing the git pile am ~ /path/to/pile command ends with the message:
"error: Patch doesn't look like a git-pile cover letter: failed to find version information"

The pile file was generated by a git-pile (in the same version) and was not modified (except for the mail client)

The problem was that the pile file contained a description where one of the lines started with the word "From"
After removing that word, everything started working.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.