git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: "Philip Peterson via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Johannes Schindelin <johannes.schindelin@gmx.de>,
	Emily Shaffer <nasamuffin@google.com>,
	Philip Peterson <philip.c.peterson@gmail.com>
Subject: [PATCH 0/5] promise: introduce promises to track success or error
Date: Sun, 18 Feb 2024 07:33:27 +0000	[thread overview]
Message-ID: <pull.1666.git.git.1708241612.gitgitgadget@gmail.com> (raw)

Hello all, this is my first patchset so thank you for being patient with me
as I learn the process and conventions of your very fine project. These
patches are intended as part of the Libification effort, to show how we
could use a Promise structure to help return values from functions.


Problems
========

We seek to make libification easier by establishing a pattern for tracking
whether a function errored in a rich way. Currently, any given function
could immediately die(), or use error() to print directly to the console,
bypassing any relevant verbosity checks. The use of die() currently makes
use of Git as a library inconvenient since it is not graceful.

Additionally, returning using return error(...) (as is commonly done) always
just returns a generic error value, -1, which provides little information.


Approach
========

I solve this problem by splitting the single return value into two return
values: error, and message. However, managing two output variables can
require some coordination, and this coordination can be abstracted away by
use of an existing pattern named Promise.


Promise Concept
===============

A promise is a contract representing "some task" that will eventually
complete. Initially a promise is considered in a pending state. When it
completes, one of two codepaths will eventually be entered: reject, or
resolve. Once resolved or rejected, the promise enters a different state
representing the result. Reject or resolve may only be called once on a
given promise.

Until now, everything I described up to this point is consistent with other
implementations, such as the ECMAScript standard for promises. However, this
implementation departs from the complexity of those promises. In this
implementation, promises are simple and canNOT be chained using .then(...)
and do NOT have any notion of automatic bubbling (via re-entering the
pending state).


Sample output and reproduction
==============================

During an error, we can have richer feedback as to what caused the problem.

% git apply garbage.patch
error: 
    could not find header
caused by:
    patch fragment without header at line 1: @@ -2 +2 @@


To reproduce this output, you can use the following patch (garbage.patch):

@@ -2 +2 @@



Goals
=====

I would love to get feedback on this approach. This patchset is kept small,
so as to serve as a minimal proof of concept. It is intended to abstract to
asynchronous use-cases even though this is only a synchronous one.
Eventually, any top-level function, such as apply_all_patches(...) would
return its output via a promise to make the library interface as clean as
possible, but this patchset does not accomplish this goal. Hopefully it can
provide a direction to go in to achieve that.


Diversion
=========

While building this patchset, I noted a bug that may not have a concrete
repro case in the master branch. The bug is that when invoking git am, it
can call out to git apply, passing many flags but interestingly not the
--quiet flag. I included a fix for this issue in the patchset.


Potential Issue
===============

There is one difficulty with this approach, which is the high level of
repetition in the code required. Tracking which promise is which is its own
source of complexity and may make mistakes more prone to happen. If anyone
has suggestions for how to make the code cleaner, I would love to hear.

Thank you, Philip

Philip Peterson (5):
  promise: add promise pattern to track success/error from operations
  apply: use new promise structures in git-apply logic as a proving
    ground
  apply: update t4012 test suite
  apply: pass through quiet flag to fix t4150
  am: update test t4254 by adding the new error text

 Makefile               |   1 +
 apply.c                | 133 +++++++++++++++++++++++++++--------------
 apply.h                |   9 ++-
 builtin/am.c           |   5 ++
 promise.c              |  89 +++++++++++++++++++++++++++
 promise.h              |  71 ++++++++++++++++++++++
 range-diff.c           |  14 +++--
 t/t4012-diff-binary.sh |   4 +-
 t/t4254-am-corrupt.sh  |   9 ++-
 9 files changed, 279 insertions(+), 56 deletions(-)
 create mode 100644 promise.c
 create mode 100644 promise.h


base-commit: 2996f11c1d11ab68823f0939b6469dedc2b9ab90
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1666%2Fphilip-peterson%2Fpeterson%2Femail-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1666/philip-peterson/peterson/email-v1
Pull-Request: https://github.com/git/git/pull/1666
-- 
gitgitgadget


             reply	other threads:[~2024-02-18  7:33 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-18  7:33 Philip Peterson via GitGitGadget [this message]
2024-02-18  7:33 ` [PATCH 1/5] promise: add promise pattern to track success/error from operations Philip Peterson via GitGitGadget
2024-02-18  7:33 ` [PATCH 2/5] apply: use new promise structures in git-apply logic as a proving ground Philip Peterson via GitGitGadget
2024-02-18  7:33 ` [PATCH 3/5] apply: update t4012 test suite Philip Peterson via GitGitGadget
2024-02-18  7:33 ` [PATCH 4/5] apply: pass through quiet flag to fix t4150 Philip Peterson via GitGitGadget
2024-02-18  7:33 ` [PATCH 5/5] am: update test t4254 by adding the new error text Philip Peterson via GitGitGadget
2024-02-19 14:25 ` [PATCH 0/5] promise: introduce promises to track success or error Phillip Wood
2024-02-20  2:57   ` Jeff King
2024-02-20 10:53     ` Phillip Wood
2024-02-20 12:19       ` Patrick Steinhardt
2024-02-20 16:20         ` Junio C Hamano
2024-02-21 18:03         ` Jeff King
2024-03-12  4:18           ` Philip

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=pull.1666.git.git.1708241612.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=johannes.schindelin@gmx.de \
    --cc=nasamuffin@google.com \
    --cc=philip.c.peterson@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).