mirror of
https://github.com/ostreedev/ostree.git
synced 2025-01-09 01:18:35 +03:00
ostree: Support for using EDITOR to fill commit subject/body
Behave similar to git when 'ostree commit' is run without a --subject or --body. Bring up an editor. The first line becomes the subject and following lines become the --body after an optional blank line. Use similar logic to git in determining EDITOR https://bugzilla.gnome.org/show_bug.cgi?id=707063
This commit is contained in:
parent
1a708accf1
commit
a4c3c4ae38
@ -44,6 +44,8 @@ ostree_SOURCES = src/ostree/main.c \
|
||||
src/ostree/ot-main.c \
|
||||
src/ostree/ot-dump.h \
|
||||
src/ostree/ot-dump.c \
|
||||
src/ostree/ot-editor.c \
|
||||
src/ostree/ot-editor.h \
|
||||
$(NULL)
|
||||
|
||||
# Admin subcommand
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "ot-builtins.h"
|
||||
#include "ot-editor.h"
|
||||
#include "ostree.h"
|
||||
#include "otutil.h"
|
||||
|
||||
@ -134,6 +135,92 @@ commit_filter (OstreeRepo *self,
|
||||
return OSTREE_REPO_COMMIT_FILTER_ALLOW;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
commit_editor (OstreeRepo *repo,
|
||||
const char *branch,
|
||||
char **subject,
|
||||
char **body,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
const char *template =
|
||||
"\n"
|
||||
"# Please enter the commit message for your changes. The first line will\n"
|
||||
"# become the subject, and the remainder the body. Lines starting\n"
|
||||
"# with '#' will be ignored, and an empty message aborts the commit.\n"
|
||||
"#\n"
|
||||
"# Branch: %s\n";
|
||||
|
||||
gs_free char *input = NULL;
|
||||
gs_free char *output = NULL;
|
||||
gboolean ret = FALSE;
|
||||
GString *bodybuf = NULL;
|
||||
char **lines = NULL;
|
||||
int i;
|
||||
|
||||
*subject = NULL;
|
||||
*body = NULL;
|
||||
|
||||
input = g_strdup_printf (template, branch);
|
||||
|
||||
output = ot_editor_prompt (repo, input, cancellable, error);
|
||||
if (output == NULL)
|
||||
goto out;
|
||||
|
||||
lines = g_strsplit (output, "\n", -1);
|
||||
for (i = 0; lines[i] != NULL; i++)
|
||||
{
|
||||
g_strchomp (lines[i]);
|
||||
|
||||
/* Lines starting with # are skipped */
|
||||
if (lines[i][0] == '#')
|
||||
continue;
|
||||
|
||||
/* Blank lines before body starts are skipped */
|
||||
if (lines[i][0] == '\0')
|
||||
{
|
||||
if (!bodybuf)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!*subject)
|
||||
{
|
||||
*subject = g_strdup (lines[i]);
|
||||
}
|
||||
else if (!bodybuf)
|
||||
{
|
||||
bodybuf = g_string_new (lines[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_string_append_c (bodybuf, '\n');
|
||||
g_string_append (bodybuf, lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!*subject)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Aborting commit due to empty commit subject.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bodybuf)
|
||||
{
|
||||
*body = g_string_free (bodybuf, FALSE);
|
||||
g_strchomp (*body);
|
||||
bodybuf = NULL;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
g_strfreev (lines);
|
||||
if (bodybuf)
|
||||
g_string_free (bodybuf, TRUE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ostree_builtin_commit (int argc, char **argv, OstreeRepo *repo, GCancellable *cancellable, GError **error)
|
||||
{
|
||||
@ -179,13 +266,6 @@ ostree_builtin_commit (int argc, char **argv, OstreeRepo *repo, GCancellable *ca
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!opt_subject)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"A subject must be specified with --subject");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (opt_owner_uid >= 0 || opt_owner_gid >= 0 || opt_statoverride_file != NULL
|
||||
|| opt_no_xattrs)
|
||||
{
|
||||
@ -205,6 +285,19 @@ ostree_builtin_commit (int argc, char **argv, OstreeRepo *repo, GCancellable *ca
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!opt_subject && !opt_body)
|
||||
{
|
||||
if (!commit_editor (repo, opt_branch, &opt_subject, &opt_body, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!opt_subject)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"A subject must be specified with --subject");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ostree_repo_prepare_transaction (repo, opt_link_checkout_speedup, NULL, cancellable, error))
|
||||
goto out;
|
||||
|
||||
|
110
src/ostree/ot-editor.c
Normal file
110
src/ostree/ot-editor.c
Normal file
@ -0,0 +1,110 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2013 Stef Walter <stefw@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Stef Walter <stefw@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ot-editor.h"
|
||||
#include "libgsystem.h"
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef DEFAULT_EDITOR
|
||||
#define DEFAULT_EDITOR "vi"
|
||||
#endif
|
||||
|
||||
/* Logic pulled from git */
|
||||
|
||||
static const char *
|
||||
get_editor (void)
|
||||
{
|
||||
const char *editor = g_getenv ("OSTREE_EDITOR");
|
||||
const char *terminal = g_getenv ("TERM");
|
||||
int terminal_is_dumb = !terminal || g_str_equal (terminal, "dumb");
|
||||
|
||||
if (!editor && !terminal_is_dumb)
|
||||
editor = g_getenv ("VISUAL");
|
||||
if (!editor)
|
||||
editor = g_getenv ("EDITOR");
|
||||
|
||||
if (!editor && terminal_is_dumb)
|
||||
return NULL;
|
||||
|
||||
if (!editor)
|
||||
editor = DEFAULT_EDITOR;
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
char *
|
||||
ot_editor_prompt (OstreeRepo *repo,
|
||||
const char *input,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gs_unref_object GSSubprocessContext *ctx = NULL;
|
||||
gs_unref_object GSSubprocess *proc = NULL;
|
||||
gs_unref_object GFile *file = NULL;
|
||||
gs_unref_object GFileIOStream *io = NULL;
|
||||
GOutputStream *output;
|
||||
const char *editor;
|
||||
char *ret = NULL;
|
||||
|
||||
editor = get_editor ();
|
||||
if (editor == NULL)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Terminal is dumb, but EDITOR unset");
|
||||
goto out;
|
||||
}
|
||||
|
||||
file = g_file_new_tmp (NULL, &io, error);
|
||||
if (file == NULL)
|
||||
goto out;
|
||||
|
||||
output = g_io_stream_get_output_stream (G_IO_STREAM (io));
|
||||
if (!g_output_stream_write_all (output, input, strlen (input), NULL, cancellable, error) ||
|
||||
!g_io_stream_close (G_IO_STREAM (io), cancellable, error))
|
||||
goto out;
|
||||
|
||||
ctx = gs_subprocess_context_newv (editor, gs_file_get_path_cached (file), NULL);
|
||||
gs_subprocess_context_set_stdin_disposition (ctx, GS_SUBPROCESS_STREAM_DISPOSITION_INHERIT);
|
||||
gs_subprocess_context_set_stdout_disposition (ctx, GS_SUBPROCESS_STREAM_DISPOSITION_INHERIT);
|
||||
gs_subprocess_context_set_stderr_disposition (ctx, GS_SUBPROCESS_STREAM_DISPOSITION_INHERIT);
|
||||
|
||||
proc = gs_subprocess_new (ctx, cancellable, error);
|
||||
if (proc == NULL)
|
||||
goto out;
|
||||
|
||||
if (!gs_subprocess_wait_sync_check (proc, cancellable, error))
|
||||
{
|
||||
g_prefix_error (error, "There was a problem with the editor '%s'.", editor);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = gs_file_load_contents_utf8 (file, cancellable, error);
|
||||
|
||||
out:
|
||||
if (file)
|
||||
(void )g_file_delete (file, NULL, NULL);
|
||||
return ret;
|
||||
}
|
30
src/ostree/ot-editor.h
Normal file
30
src/ostree/ot-editor.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2013 Stef Walter <stefw@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Stef Walter <stefw@redhat.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "ostree.h"
|
||||
|
||||
char * ot_editor_prompt (OstreeRepo *repo, const char *input,
|
||||
GCancellable *cancellable, GError **error);
|
Loading…
Reference in New Issue
Block a user