Skip to content

Add functionality to clone remote repository. #1548

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

Open
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

jeremypw
Copy link
Collaborator

@jeremypw jeremypw commented Apr 3, 2025

By default pulls requested named repo from "https://github.com/elementary" and clones into a repo of the same name in the parent of the current project.

Optionally makes it the active project after cloning.

The functionality is exposed in the actionbar at the bottom of the sidebar. To avoid forcing the sidebar too wide, the text is shortened and the buttons are put in a FlowBox similar to the search bar.

Suggestions for alternatives welcome.

Screenshot from 2025-05-27 16 38 43
Screenshot from 2025-05-27 16 40 02

@jeremypw jeremypw marked this pull request as ready for review May 18, 2025 16:06
@jeremypw jeremypw mentioned this pull request May 26, 2025
10 tasks
@jeremypw jeremypw requested a review from a team May 27, 2025 15:44
Copy link
Member

@danirabbit danirabbit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm cloning a repository, I'm almost always either typing the full path or going to this page and hitting the copy button:

Screenshot from 2025-05-27 09 37 44

Screenshot from 2025-05-27 09 38 42

But this form seems to expect different entries for the remote URL and repository path. Is that right? I'm not exactly sure how to fill out the form as written tbh

repository_name_entry = new Granite.ValidatedEntry.from_regex (name_regex) {
activates_default = false
};
repository_local_folder_entry = new Granite.ValidatedEntry.from_regex (local_folder_regex) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should use a file chooser because we need to make sure Code has access in the documents portal to this folder


private class CloneEntry : Gtk.Box {
public CloneEntry (string label_text, Gtk.Widget entry) {
var label = new Gtk.Label (label_text) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to make sure to set mnemonic_widget property so that entries are labeled for the screen reader

Comment on lines +47 to +53
repository_local_folder_entry.text = local_folder;
repository_host_uri_entry.text = "https://github.com";
repository_user_entry.text = "elementary";
repository_name_entry.text = "";
repository_local_name_entry.text = "";

on_is_valid_changed ();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should all happen in the construct block. Only things necessary for the Object call should happen in a constructor

Comment on lines +48 to +49
repository_host_uri_entry.text = "https://github.com";
repository_user_entry.text = "elementary";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be placeholder text, not pre-filled text

Comment on lines +50 to +51
repository_name_entry.text = "";
repository_local_name_entry.text = "";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Text is empty by default. I'm not sure why you're setting it empty again?

repository_host_uri_entry = new Granite.ValidatedEntry.from_regex (url_regex) {
activates_default = false
};
repository_user_entry = new Granite.ValidatedEntry.from_regex (name_regex) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

activates_default = false
};
repository_user_entry = new Granite.ValidatedEntry.from_regex (name_regex) {
activates_default = false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are these set to activates_default = false? Usually you can activate from any part of the form in case you need to go back and make a correction

add_button (_("Cancel"), Gtk.ResponseType.CANCEL);
primary_text = _("Create a local clone of a Git repository");
///TRANSLATORS "Git" is a proper name and must not be translated
secondary_text = _("The source repository and local folder must exist and be accessible");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does "be accessible" mean in this context?


add_button (_("Cancel"), Gtk.ResponseType.CANCEL);
primary_text = _("Create a local clone of a Git repository");
///TRANSLATORS "Git" is a proper name and must not be translated
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is probably meant to be above the preceding line

activates_default = false,
width_chars = 50
};
repository_local_name_entry = new Granite.ValidatedEntry.from_regex (name_regex) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably auto fill when the repository URL is changed

Comment on lines +1 to +20
/*
* Copyright 2025 elementary, Inc. (https://elementary.io)
*
* 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 2 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, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Authored by: Jeremy Wootten <jeremywootten@gmail.com>
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For new files it would be nice to use the SPDX header:

Suggested change
/*
* Copyright 2025 elementary, Inc. (https://elementary.io)
*
* 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 2 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, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Authored by: Jeremy Wootten <jeremywootten@gmail.com>
*/
/*
* SPDX-License-Identifier: GPL-2.0-or-later
* SPDX-FileCopyrightText: 2025 elementary, Inc. <https://elementary.io>
*
* Authored by: Jeremy Wootten <jeremywootten@gmail.com>
*/

primary_text = _("Create a local clone of a Git repository");
///TRANSLATORS "Git" is a proper name and must not be translated
secondary_text = _("The source repository and local folder must exist and be accessible");
badge_icon = new ThemedIcon ("download");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not an icon name that exists. You could do:
browser-download
Screenshot from 2025-05-27 11 57 26

or emblem-downloads. I would probably do this one, personally
Screenshot from 2025-05-27 12 00 06

secondary_text = _("The source repository and local folder must exist and be accessible");
badge_icon = new ThemedIcon ("download");

repository_host_uri_entry = new Granite.ValidatedEntry.from_regex (url_regex) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to set input_purpose for virtual keyboards:

Suggested change
repository_host_uri_entry = new Granite.ValidatedEntry.from_regex (url_regex) {
repository_host_uri_entry = new Granite.ValidatedEntry.from_regex (url_regex) {
input_purpose = URL,

};
repository_local_folder_entry = new Granite.ValidatedEntry.from_regex (local_folder_regex) {
activates_default = false,
width_chars = 50
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for adding width_chars here?

var clone_button = new Gtk.Button.from_icon_name ("folder-open-symbolic", Gtk.IconSize.SMALL_TOOLBAR) {
action_name = Scratch.MainWindow.ACTION_PREFIX + Scratch.MainWindow.ACTION_CLONE_REPO,
always_show_image = true,
label = _("Clone …"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No space before ellipsis

Suggested change
label = _("Clone "),
label = _("Clone…"),


var clone_button = new Gtk.Button.from_icon_name ("folder-open-symbolic", Gtk.IconSize.SMALL_TOOLBAR) {
action_name = Scratch.MainWindow.ACTION_PREFIX + Scratch.MainWindow.ACTION_CLONE_REPO,
always_show_image = true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably shouldn't construct new image buttons in this way since you can't do this in GTK4. You have to put an image and a label in a box and pack that

@@ -60,7 +60,16 @@ public class Code.Sidebar : Gtk.Grid {
action_name = Scratch.MainWindow.ACTION_PREFIX + Scratch.MainWindow.ACTION_OPEN_FOLDER,
action_target = new Variant.string (""),
always_show_image = true,
label = _("Open Folder…")
label = _("Open …"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No space before ellipsis

Suggested change
label = _("Open "),
label = _("Open…"),

xalign = 0.0f
};

var clone_button = new Gtk.Button.from_icon_name ("folder-open-symbolic", Gtk.IconSize.SMALL_TOOLBAR) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about making these model buttons at the end of the project selection popover?

@jeremypw
Copy link
Collaborator Author

@danirabbit Thanks for the detailed review! I'll get working on your comments. Regarding the dialog, I was trying to reduce the amount of typing required to specify the remote URL especially if you are cloning an elementary repository. I too usually copy paste the URL from github because I use the terminal command git clone .. anyway. I was trying to make the UI easier by only having to type the name of the project for the default situation but if it confuses then maybe I should just have one entry for the URL? I'll rethink the dialog.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants