//
// aegis - project change supervisor
// Copyright (C) 2001, 2004-2008 Peter Miller
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
// .
//
#include
#include
#include
#include
#include
#include
#include
static void
destructor(format_ty *)
{
}
static int
is_a_candidate(format_ty *, string_ty *filename)
{
char *cp;
cp = strrchr(filename->str_text, '/');
if (cp)
++cp;
else
cp = filename->str_text;
return (cp[0] == 's' && cp[1] == '.' && cp[2]);
}
static string_ty *
sanitize(format_ty *, string_ty *filename, int last_part)
{
size_t j;
//
// Break the filename into path elements.
//
string_list_ty sl;
sl.split(filename, "/");
//
// get rid of path elements named "SCCS"
//
string_list_ty sl2;
for (j = 0; j < sl.nstrings; ++j)
{
string_ty *s;
s = sl.string[j];
if (strcasecmp(s->str_text, "sccs"))
sl2.push_back(s);
}
if (last_part)
{
//
// Remove the "s." from the beginning of the last path element.
//
if (sl2.nstrings)
{
string_ty *s;
s = sl2.string[sl2.nstrings - 1];
if
(
s->str_length > 2
&&
s->str_text[0] == 's'
&&
s->str_text[1] == '.'
)
{
sl2.string[sl2.nstrings - 1] =
str_n_from_c(s->str_text + 2, s->str_length - 2);
str_free(s);
}
}
}
//
// Rebuild the filename from the remaining path elements.
//
return sl2.unsplit("/");
}
static format_version_ty *
read_versions(format_ty *, string_ty *physical, string_ty *logical)
{
return sccs_parse(physical, logical);
}
static string_ty *
history_put(format_ty *)
{
//
// The ae-sccs-put script is distributed with Aegis.
//
return
str_from_c
(
"ae-sccs-put -G${quote $input} "
"-y${quote (${version}) ${change description}} "
"${quote ${dirname $history}/s.${basename $history}}");
}
static string_ty *
history_get(format_ty *)
{
//
// get -r get the specified version
// get -G output to file
// get -s work silently
// get -k no keyword expansion
//
return
str_from_c
(
"sccs get -r${quote $edit} -s -k -G${quote $output} "
"${quote ${dirname $history}/s.${basename $history}}"
);
}
static string_ty *
history_query(format_ty *)
{
return
str_from_c
(
"sccs get -t -g ${quote ${dirname $history}/s.${basename $history}}"
);
}
static string_ty *
diff(format_ty *)
{
//
// I'd prefer to say "diff -U10", but we can't rely on GNU
// Diff being installed everywhere. It's a risk even using
// a context diff, because not all non-GNU diff progs have -c.
//
return
str_from_c
(
"set +e; "
CONF_DIFF " "
#ifdef HAVE_GNU_DIFF
"-U10 --text "
#else
"-c "
#endif
"${quote $original} ${quote $input} > ${quote $output}; "
"test $? -le 1"
);
}
static string_ty *
merge(format_ty *)
{
//
// This is the RCS merge command.
// SCCS doesn't have one of its own.
//
return
str_from_c
(
"set +e; "
"merge -p -L baseline -L C$c ${quote $mostrecent} "
"${quote $original} ${quote $input} > ${quote $output}; "
"test $? -le 1"
);
}
static void
unlock(format_ty *, string_ty *filename)
{
int flags;
string_ty *cmd;
string_ty *qfn;
//
// -di no keyword expansion
//
qfn = str_quote_shell(filename);
cmd = str_format("sccs admin -di %s", qfn->str_text);
str_free(qfn);
flags = OS_EXEC_FLAG_ERROK;
os_execute(cmd, flags, os_curdir());
str_free(cmd);
}
static format_vtable_ty vtbl =
{
sizeof(format_ty),
destructor,
is_a_candidate,
sanitize,
read_versions,
history_put,
history_get,
history_query,
diff,
merge,
unlock,
};
format_ty *
format_sccs_new(void)
{
return format_new(&vtbl);
}