Closed Angelk90 closed 3 years ago
Hi @Angelk90
let url = URL(string: "https://github.com/github/hub.git")!
let repo = GitRepository(from: url)
do {
try repo.clone(at: "/Users/\(userName)/Desktop/hub")
let references = try repo.listReferences()
print(references.remoteBranches.map({$0.name}))
} catch let e {
print("Error \(e).")
}
Please ensure you are using a proper user name that is on your system. Also if you will use try
instead of try?
you should see the exact error in your catch block.
You may also try to use try repo.cloneAtTemporaryPath()
method to get the repo into some temporary path (the repo will be deleted as soon as the instance is released by Swift).
Alternatively, get a path to Desktop from the system:
guard let desktopPath = NSSearchPathForDirectoriesInDomains(.desktopDirectory,
.userDomainMask,
true).first else { return }
let url = URL(string: "https://github.com/github/hub.git")!
let repo = GitRepository(from: url)
do {
try repo.clone(at: "\(desktopPath)/hub")
} catch let e {
print("Error \(e).")
}
@way-to-code :
I get the following error:
Error cloneError(message: "xcrun: error: cannot be used within an App Sandbox.").
Did I forget something to disable?
It seems you have Sandboxed application (macOS feature). You need to turn off Sandbox in your Xcode project. As for now the app can not access anything except own documents.
Hi @way-to-code ,
Thank you, congratulations you have created a magnificent project.
It would be very useful to have a basic project example.
One last thing at the moment I'm not able to figure out how to use Receiving the progress
What I want to do is this I have a progress bar, as seen in the image, every time the cloning process progresses I would like to grow the progress bar until the cloning process ends.
The problem is the following, when I try to print the value I get the following errors, how should I declare them.
@way-to-code : I tried to do this but it is not working, when the report is cloned, the repository
function is not called.
Where am I doing wrong?
class ProgressTracker: RepositoryDelegate {
lazy var progressBlock: ((String) -> Void)? = nil
func repository(_ repository: Repository, didProgressClone progress: String) {
print("ProgressTracker", progress)
self.progressBlock?(progress)
}
}
struct File: View {
@State var pathUrl = "https://github.com/way-to-code/git-macOS.git"
@State var nameDir = "/Users/\(nameUser)/Desktop/git-macOS"
var progressTracker = ProgressTracker()
func cloneReport() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
let url: URL = URL(string: pathUrl)!
let report = GitRepository(from: url)
report.delegate = progressTracker
progressTracker.progressBlock = { progress in
print("File", progress)
}
do {
try report.clone(at: nameDir)
} catch let e {
print("Errors \(e).")
}
}
}
var body: some View {
Button(action: {
cloneReport()
}) {
Text("Clone").frame(width: 330)
}
}
}
@Angelk90 I assume that you are blocking the main thread when cloning a repository. I would suggest to redirect the clone operation into a background thread. When you call any operation on repository, the calling thread is blocked until the operation is finished.
For local operations like checkout or listing branches it is not so critical, but for the clone, it would definitely behave not in a way you expect.
Also I have added Demo project to the repository demonstrating how the clone can be implemented.
Speaking of the clone in general, I'm afraid it would not be so easy to implement the gauge indicator that you are speaking about. Git output gives a raw text with progress, not integer or double values. You may try to parse the output in your app, but it would be a bit fragile (as the format may change in future). I would suggest you to use an infinite loading indicator with raw text output (like done in Demo). From my perspective it will be the most easy and stable way.
Hope this will help! :)
@way-to-code :
My goal was to develop such a thing, see where there is the icon
with thepercentage 21%
next to it, I wanted to make that when thereport
was cloned, the percentage would be activated in the menu bar, which it gradually increased until the cloning was finished.
Some doubts:
1) I tried to clone a report that has only the main (master) as a branch, when it was cloned it printed what you see is printed twice main
and thenHEAD
why?
2) I modified the repository
function by putting inappendLog
the writing ->
then followed by the message, but the writings that do not contain the ->
symbol is because the messages that do not have it are printed with the one before who owns it?
I don't know if I was able to explain myself well.
Considerations on the example:
1) As you can see from the image the log is editable, I made a pull request not the modification that cannot be written.
2) As you can see in the image of the log, using the dark mode the writings are not seen, not knowing the storyboard very well I do not know how to fix it but I report it anyway.
Other considerations:
1) Reading this using the following framework is it not possible to publish on the appstore? Do you think a solution can be found in the future?
// Please note that App Sandbox is disabled in the entitlements file.
// When App Sandbox is enabled the app can not access anything except own documents.
// However, without App Sandboox apps won't be accepted by Appstore.
// If Appstore is your goal, please do not use Git.framework and consider other alternatives.
2) How exactly does temporary cloning work? If I build the app with the export, then I use it on another pc, but the cloning is temporary what happens?
@Angelk90
I tried to clone a report that has only the main (master) as a branch, when it was cloned it printed what you see is printed twice main and then HEAD why?
This is expected behaviour. One is refs/heads/main
, another one is refs/remotes/origin/main
(local reference and remote reference). If you need to distinguish them, you can use remoteBranches
and localBranches
methods on GitReferenceList
.
I modified the repository function by putting in appendLog the writing -> then followed by the message, but the writings that do not contain the -> symbol is because the messages that do not have it are printed with the one before who owns it?
This is how the command line output is received. It can be received line by line or many lines at ones. I don't think we have a control for it. You can split the lines by \n
in your app and then parse it.
Also consider reading this post in stack overflow. Git clone process consist of several stages. You need to consider this.
As you can see from the image the log is editable, I made a pull request not the modification that cannot be written.
Merged
As you can see in the image of the log, using the dark mode the writings are not seen, not knowing the storyboard very well I do not know how to fix it but I report it anyway.
It wasn't my goal to make the ideal UI for Demo considering all corner cases :) I guess the source of the problem is NSTextView which expects NSAttributedString
. As for now the attributed string is created from the input string, but without any style copied from the current theme.
Reading this using the following framework is it not possible to publish on the appstore? Do you think a solution can be found in the future?
You can try to bundle git with your application. Potentially this can be a solution. Another potential problem with Appstore was described in Wiki page here. I have not analysed the problem, as Appstore was not my goal. So all further investigations at your own risk.
How exactly does temporary cloning work? If I build the app with the export, then I use it on another pc, but the cloning is temporary what happens?
This is just a way to clone a repository at some path that you do not care about, read some files and forget about the repo. I don't think this is your case. As an example - Continuous Integration (when you need to read some files from git for instance)
So summarising this works the same as ordinary clone, but at some temporary path. When an instance of a repository is deallocated, the folder with the repo will be removed.
@way-to-code: I wonder then how did they all apps for mac os who use git?
I do not know how other apps in Appstore use git. In my experience all major git applications like Tower for example, are not distributed throw Appstore. If you can make a research for it it will be cool :)
As this issue topic has been resolved, mark the issue as Closed. Thanks.
@way-to-code , regarding this:
This is how the command line output is received. It can be received line by line or many lines at ones. I don't think we have a control for it. You can split the lines by \n in your app and then parse it.
Also consider reading this post in stack overflow. Git clone process consist of several stages. You need to consider this. I wrote the following function, you must definitely fix it but it returns a result on the percentage of the cloning process.
I have divided the following areas Counting
, Compressing
, Receiving
and Resolving
each with 25%
of the whole process.
Then everyone can consider it differently, but I think it can be an opportunity to have something in the future, if it can be of help for someone else.
func matches(for regex: String, in text: String) -> [String] {
do {
let regex = try NSRegularExpression(pattern: regex)
let results = regex.matches(in: text, range: NSRange(text.startIndex..., in: text))
return results.map {
String(text[Range($0.range, in: text)!])
}
} catch let error {
print("invalid regex: \(error.localizedDescription)")
return []
}
}
func calculateNumber(_ word:String) -> Double {
var matched = matches(for: "([0-9]+/[0-9]+)", in: word)
let last = matched[matched.endIndex - 1]
matched = matches(for: "[0-9]+", in: last)
return Double(matched[0])! / Double(matched[1])!
}
func words(_ word:String) -> Int {
var number = 0
if word.contains("Counting objects:"){
let result = calculateNumber(word)
number = Int(result*25)
}
if word.contains("Compressing objects:"){
let result = calculateNumber(word)
number = 25 + Int(result*25)
}
if word.contains("Receiving objects:"){
let result = calculateNumber(word)
number = 50 + Int(result*25)
}
if word.contains("Resolving deltas:"){
let result = calculateNumber(word)
number = 75 + Int(result*25)
}
return number
}
Hi @way-to-code ,
Would it be possible to have a working example of using the framework? I am unable to clone the specified report to the specified path.
What am I doing wrong?