Skip to content

Commit

Permalink
Added user credentials when opening remote projects
Browse files Browse the repository at this point in the history
  • Loading branch information
D. Alfano (Nexus6) committed Oct 31, 2023
1 parent 39b2623 commit 9986a73
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 39 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ SRCS += src/ui/Editor.cpp
SRCS += src/ui/EditorContextMenu.cpp
SRCS += src/ui/EditorTabManager.cpp
SRCS += src/ui/GenioWindow.cpp
SRCS += src/ui/GitCredentialsWindow.cpp
SRCS += src/ui/GoToLineWindow.cpp
SRCS += src/ui/IconCache.cpp
SRCS += src/ui/ProblemsPanel.cpp
Expand Down
12 changes: 9 additions & 3 deletions src/helpers/git/GitRepository.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,19 +148,25 @@ namespace Genio::Git {
}

const BPath&
GitRepository::Clone(const string& url, const BPath& localPath, git_indexer_progress_cb callback)
GitRepository::Clone(const string& url, const BPath& localPath,
git_indexer_progress_cb callback,
git_credential_acquire_cb authentication_callback)
{
git_libgit2_init();
git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
callbacks.transfer_progress = callback;
clone_opts.fetch_opts.callbacks = callbacks;
clone_opts.fetch_opts.callbacks.credentials = authentication_callback;

git_repository *repo = nullptr;

int error = git_clone(&repo, url.c_str(), localPath.Path(), &clone_opts);
if (error != 0) {
throw std::runtime_error(git_error_last()->message);
if (error < 0) {
if (error == CANCEL_CREDENTIALS)
throw std::runtime_error("CANCEL_CREDENTIALS");
else
throw std::runtime_error(git_error_last()->message);
}
return localPath;
}
Expand Down
29 changes: 16 additions & 13 deletions src/helpers/git/GitRepository.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
* Copyright 2023 Nexus6 <[email protected]>
* All rights reserved. Distributed under the terms of the MIT license.
* Based on TrackGit (https://github.com/HaikuArchives/TrackGit)
* Original author: Hrishikesh Hiraskar <[email protected]>
* Original author: Hrishikesh Hiraskar <[email protected]>
* Copyright Hrishikesh Hiraskar and other HaikuArchives contributors (see GitHub repo for details)
*/

#pragma once

#include <SupportDefs.h>
Expand Down Expand Up @@ -33,6 +33,8 @@ using namespace std::filesystem;

namespace Genio::Git {

const int CANCEL_CREDENTIALS = -123;

class GitException {
public:
GitException(int error, BString const& message)
Expand All @@ -45,37 +47,38 @@ namespace Genio::Git {

int Error() noexcept { return _error; }
BString Message() noexcept { return _message; }

private:
int _error;
BString _message;
};

class GitRepository {
class GitRepository {
public:
GitRepository(const path& path);
~GitRepository();

const BPath& Clone(const string& url, const BPath& localPath,
git_indexer_progress_cb callback);


const BPath& Clone(const string& url, const BPath& localPath,
git_indexer_progress_cb callback,
git_credential_acquire_cb authentication_callback);

bool InitCheck() { return fInitCheck; };
void Init(const path& repo, const path& localPath);

vector<string> GetBranches();
int SwitchBranch(string branch);

vector<pair<string, string>> GetFiles();

string PullChanges(bool rebase);

private:
git_repository *fRepository;
path fRepositoryPath;
bool fInitCheck;

string _ExecuteCommand(const string& command) const;

};

}
70 changes: 70 additions & 0 deletions src/ui/GitCredentialsWindow.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright Hrishikesh Hiraskar <[email protected]>
* Copyright 2023 Nexus6 <[email protected]>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "GitCredentialsWindow.h"

#include <stdio.h>
#include <string.h>

#include <AppKit.h>
#include <Catalog.h>
#include <LayoutBuilder.h>
#include <SupportKit.h>

#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "GitCredentialsWindow"

GitCredentialsWindow::GitCredentialsWindow(char* usernamePtr, char* passwordPtr)
:
BWindow(BRect(0, 0, 300, 150), B_TRANSLATE("Git - User Credentials"),
B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE
| B_AUTO_UPDATE_SIZE_LIMITS | B_NOT_CLOSABLE)
{
fUsernamePtr = usernamePtr;
fPasswordPtr = passwordPtr;

fUsername = new BTextControl(B_TRANSLATE("Username:"), "", NULL);
fPassword = new BTextControl(B_TRANSLATE("Password:"), "", NULL);
fPassword->TextView()->HideTyping(true);
BButton* fOK = new BButton("ok", B_TRANSLATE("OK"),
new BMessage(kCredOK));
BButton* fCancel = new BButton("cancel", B_TRANSLATE("Cancel"),
new BMessage(kCredCancel));

BLayoutBuilder::Group<>(this, B_VERTICAL)
.SetInsets(B_USE_WINDOW_INSETS)
.AddGrid()
.AddTextControl(fUsername, 0, 0)
.AddTextControl(fPassword, 0, 1)
.End()
.AddGroup(B_HORIZONTAL)
.AddGlue()
.Add(fCancel)
.Add(fOK)
.End();

CenterOnScreen();
Show();
}


void
GitCredentialsWindow::MessageReceived(BMessage* msg)
{
switch (msg->what) {
case kCredOK:
strcpy(fUsernamePtr, fUsername->Text());
strcpy(fPasswordPtr, fPassword->Text());
Quit();
break;
case kCredCancel:
strcpy(fUsernamePtr, "");
strcpy(fPasswordPtr, "");
Quit();
break;
// default:
// BWindow::MessageReceived(msg);
}
}
43 changes: 43 additions & 0 deletions src/ui/GitCredentialsWindow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2018, Hrishikesh Hiraskar <[email protected]>
* All rights reserved. Distributed under the terms of the MIT license.
*/

#ifndef _CREDENTIALS_WINDOW_H_
#define _CREDENTIALS_WINDOW_H_

#include <posix/sys/time.h>

#include <InterfaceKit.h>

enum {
kCredOK,
kCredCancel
};

/**
* The Credentials Window class.
*/
class GitCredentialsWindow : public BWindow {
/**
* The text control for username.
*/
BTextControl* fUsername;
/**
* The text control for password.
*/
BTextControl* fPassword;
/**
* The username pointer.
*/
char* fUsernamePtr;
/**
* The password pointer.
*/
char* fPasswordPtr;
public:
GitCredentialsWindow(char*, char*);
virtual void MessageReceived(BMessage*);
};

#endif
86 changes: 63 additions & 23 deletions src/ui/RemoteProjectWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <AppKit.h>
#include <Catalog.h>
#include <ControlLook.h>
#include <git2.h>
#include <LayoutBuilder.h>
#include <SeparatorView.h>
#include <StatusBar.h>
Expand All @@ -19,6 +20,8 @@
#include <Window.h>

#include "GenioWindowMessages.h"
#include "GitCredentialsWindow.h"
#include "GitRepository.h"
#include "Utils.h"

#include "BeDC.h"
Expand Down Expand Up @@ -159,9 +162,11 @@ RemoteProjectWindow::MessageReceived(BMessage* msg)
_SetProgress(100, "Finished!");
fButtonsLayout->SetVisibleItem(VIEW_INDEX_CLOSE_BUTTON);
} catch(std::exception &ex) {
OKAlert("OpenRemoteProject", BString("An error occurred while opening a remote project: ")
<< ex.what(), B_INFO_ALERT);
fStatusText->SetText("An error occurred!");
if (BString(ex.what()) != "CANCEL_CREDENTIALS") {
OKAlert("OpenRemoteProject", BString("An error occurred while opening a remote project: ")
<< ex.what(), B_INFO_ALERT);
fStatusText->SetText("An error occurred!");
}
_SetIdle();
}
_ResetControls();
Expand All @@ -178,25 +183,59 @@ RemoteProjectWindow::MessageReceived(BMessage* msg)
fURL->SetEnabled(false);

auto callback = [](const git_transfer_progress *stats, void *payload) -> int {
int current_progress = stats->total_objects > 0 ?
(100*stats->received_objects) /
stats->total_objects :
0;
int kbytes = stats->received_bytes / 1024;

BString progressString;
progressString << "Cloning "
<< stats->received_objects << "/"
<< stats->total_objects << " objects"
<< " (" << kbytes << " kb)";

BMessage msg(kProgress);
msg.AddString("progress_text", progressString);
msg.AddFloat("progress_value", current_progress);
BMessenger(this_handler).SendMessage(&msg);
return 0;
};

// taken from TrackGit
auto authentication_callback = [](git_cred** out, const char* url,
const char* username_from_url,
unsigned int allowed_types,
void* payload) -> int {
char username[39], password[128];
int error = 0;

// strcpy(username, username_from_url);

GitCredentialsWindow* window = new GitCredentialsWindow(username, password);

thread_id thread = window->Thread();
status_t win_status = B_OK;
wait_for_thread(thread, &win_status);

if (BString(username) != "" && BString(password) != "") {
if (allowed_types & GIT_CREDENTIAL_SSH_KEY) {
// error = git_credential_ssh_key_new(out, username, pubkey, privkey, password);
error = git_credential_ssh_key_from_agent(out, username);
} else {
error = git_cred_userpass_plaintext_new(out, username, password);
}
}

/**
* If user cancels the credentials prompt, the username is empty.
* Cancel the command in such case.
*/
if (strlen(username) == 0)
return CANCEL_CREDENTIALS;

int current_progress = stats->total_objects > 0 ?
(100*stats->received_objects) /
stats->total_objects :
0;
int kbytes = stats->received_bytes / 1024;

BString progressString;
progressString << "Cloning "
<< stats->received_objects << "/"
<< stats->total_objects << " objects"
<< " (" << kbytes << " kb)";

BMessage msg(kProgress);
msg.AddString("progress_text", progressString);
msg.AddFloat("progress_value", current_progress);
BMessenger(this_handler).SendMessage(&msg);
return 0;
};
return error;
};

BPath fullPath(fPathBox->Path());
fullPath.Append(fDestDir->Text());
Expand All @@ -208,10 +247,11 @@ RemoteProjectWindow::MessageReceived(BMessage* msg)
std::bind
(
&GitRepository::Clone,
&repo ,
&repo,
fURL->Text(),
fullPath,
callback
callback,
authentication_callback
)
);

Expand Down

0 comments on commit 9986a73

Please sign in to comment.