Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HPCC-31095 Report an error if eclcc fails to update the local copy of a git repo #18326

Merged
merged 1 commit into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion ecl/eclcc/eclcc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1252,6 +1252,12 @@ void EclCC::processSingleQuery(const EclRepositoryManager & localRepositoryManag
}

IErrorReceiver & errorProcessor = *severityMapper;
//Associate the error handler - so that failures to fetch from git can be reported as errors, but also mapped
//to warnings to ensure that automated tasks do not fail because the could not connect to git.
localRepositoryManager.setErrorReceiver(&errorProcessor);
//Ensure the error processor is cleared up when we exit this function
COnScopeExit scoped([&]() { localRepositoryManager.setErrorReceiver(NULL); });

//All dlls/exes are essentially cloneable because you may be running multiple instances at once
//The only exception would be a dll created for a one-time query. (Currently handled by eclserver.)
instance.wu->setCloneable(true);
Expand Down Expand Up @@ -1507,7 +1513,10 @@ void EclCC::processSingleQuery(const EclRepositoryManager & localRepositoryManag
{
StringBuffer s;
e->errorMessage(s);
errorProcessor.reportError(3, s.str(), defaultErrorPathname, 1, 0, 0);
unsigned errorCode = e->errorCode();
if ((errorCode < HQL_ERROR_START) || (errorCode > HQL_ERROR_END))
errorCode = ERR_UNKNOWN_EXCEPTION;
errorProcessor.reportError(errorCode, s.str(), defaultErrorPathname, 1, 0, 0);
e->Release();
}

Expand Down
4 changes: 4 additions & 0 deletions ecl/hql/hqlerrors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,10 @@
#define ERR_INVALID_PROBABILITY 2403
#define ERR_DEFAULT_VIRTUAL_CLASH 2404
#define ERR_EMBEDERROR 2405
#define ERR_FAIL_CLONE_REPO 2406
#define ERR_FAIL_UPDATE_REPO 2407
#define ERR_CANNOT_RESOLVE_BRANCH 2408
#define ERR_UNKNOWN_EXCEPTION 2409

#define ERR_CPP_COMPILE_ERROR 2999

Expand Down
25 changes: 21 additions & 4 deletions ecl/hql/hqlrepository.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -821,14 +821,18 @@ IEclSourceCollection * EclRepositoryManager::resolveGitCollection(const char * r
}

bool ok = false;
Owned<IError> error;
CCycleTimer gitDownloadTimer;
if (alreadyExists)
{
if (options.updateRepos)
{
unsigned retCode = runGitCommand(nullptr, "fetch origin", repoPath, true);
if (retCode != 0)
DBGLOG("Failed to download the latest version of %s", defaultUrl);
{
VStringBuffer msg("Failed to download the latest version of '%s' error code (%u)", defaultUrl, retCode);
error.setown(createError(CategoryError, SeverityError, ERR_FAIL_UPDATE_REPO, msg.str(), nullptr, 0, 0, 0));
}
}

ok = true;
Expand All @@ -844,17 +848,30 @@ IEclSourceCollection * EclRepositoryManager::resolveGitCollection(const char * r
VStringBuffer params("clone %s \"%s\" --no-checkout", repoUrn.str(), repo.str());
unsigned retCode = runGitCommand(nullptr, params, options.eclRepoPath, true);
if (retCode != 0)
throw makeStringExceptionV(99, "Failed to clone dependency '%s'", defaultUrl);
{
VStringBuffer msg("Failed to clone dependency '%s' error code (%u)", defaultUrl, retCode);
error.setown(createError(CategoryError, SeverityError, ERR_FAIL_CLONE_REPO, msg.str(), nullptr, 0, 0, 0));
}
ok = true;
}
}
gitDownloadCycles += gitDownloadTimer.elapsedCycles();
if (error)
{
if (errorReceiver)
{
error.setown(errorReceiver->mapError(error)); // MORE: This mapping should really be done within reportError()
errorReceiver->report(error);
}
else
throw error.getClear();
}

if (!ok)
throw makeStringExceptionV(99, "Cannot locate the source code for dependency '%s'. --fetchrepos not enabled", defaultUrl);

if (startsWith(version, "semver:"))
throw makeStringExceptionV(99, "Semantic versioning not yet supported for dependency '%s'.", defaultUrl);
throw makeStringExceptionV(ERR_CANNOT_RESOLVE_BRANCH, "Semantic versioning not yet supported for dependency '%s'.", defaultUrl);

// Really the version should be a SHA, but for flexibility version could be a sha, a tag or a branch (on origin).
// Check for a remote branch first - because it appears that when git clones a repo, it creates a local branch for
Expand All @@ -879,7 +896,7 @@ IEclSourceCollection * EclRepositoryManager::resolveGitCollection(const char * r
DBGLOG("Version '%s' resolved to sha '%s'", version.str(), sha.str());

if (sha.isEmpty())
throw makeStringExceptionV(99, "Branch/tag '%s' could not be found for dependency '%s'.", version.str(), defaultUrl);
throw makeStringExceptionV(ERR_CANNOT_RESOLVE_BRANCH, "Branch/tag '%s' could not be found for dependency '%s'.", version.str(), defaultUrl);

path.append(repoPath).appendf("/.git/{%s", sha.str());
if (options.gitUser)
Expand Down
6 changes: 5 additions & 1 deletion ecl/hql/hqlrepository.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ class HQL_API EclRepositoryManager
}

IEclSourceCollection * resolveGitCollection(const char * repoPath, const char * defaultUrl);

void setErrorReceiver(IErrorReceiver * _errorReceiver) const
{
errorReceiver = _errorReceiver;
}
protected:
IEclRepository * createNewSourceFileEclRepository(IErrorReceiver *errs, const char * path, unsigned flags, unsigned trace, bool includeInArchive);
IEclRepository * createGitRepository(IErrorReceiver *errs, const char * path, const char * urn, unsigned flags, unsigned trace, bool includeInArchive);
Expand All @@ -85,6 +88,7 @@ class HQL_API EclRepositoryManager
IEclPackage * queryRepository(IIdAtom * name, const char * defaultUrl, IEclSourceCollection * overrideSource, bool includeDefinitions);

private:
mutable IErrorReceiver * errorReceiver = nullptr; // mutable to allow const methods to set it, it logically doesn't change the object
using DependencyInfo = std::pair<std::string, Shared<IEclPackage>>;
CIArrayOf<EclRepositoryMapping> repos;
std::vector<DependencyInfo> dependencies;
Expand Down
Loading