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

pull or fetch available? #20

Closed
fbpyr opened this issue Apr 1, 2022 · 14 comments · Fixed by #21
Closed

pull or fetch available? #20

fbpyr opened this issue Apr 1, 2022 · 14 comments · Fixed by #21
Labels
enhancement New feature or request

Comments

@fbpyr
Copy link
Contributor

fbpyr commented Apr 1, 2022

maybe a duplicate of #5 (?)
or maybe I have overlooked something,
but I did not find a way to pull l or fetch in gittyup or hlibgit2.
does it exist, or are there plans to support it?
or is it blocked somewhere upstream?

thank you. 🙂

@disruptek
Copy link
Owner

It's missing from upstream, or was. I haven't checked recently. Once libgit2 has it, it's easy for us to add it.

@fbpyr
Copy link
Contributor Author

fbpyr commented Apr 1, 2022

oh I see - it is missing even further upstream in libgit2..

@disruptek
Copy link
Owner

Yeah, I'd really like to have shallow checkout also. 😞

@fbpyr
Copy link
Contributor Author

fbpyr commented Sep 9, 2022

@disruptek I looked through some non-nim libs binding gitlib2.
As far as I understood libgit2 will not implement these 'porcelain' commands like pull,
so some libgit2 wrapper libs like libgit2sharp do implement it themselves
( https://github.com/libgit2/libgit2sharp/tree/master/LibGit2Sharp/Commands ),
while others like pygit2 do not (yet?), which makes users struggle to implement it themselves
(https://github.com/MichaelBoselowitz/pygit2-examples/blob/268c0ad25f02c288d7bdcf032d0d27afbf799691/examples.py#L58) .

@disruptek , @haxscramper in the case of gittyup, would you see pull in hlibgit2 or in gittyup?

@haxscramper
Copy link
Collaborator

hlibgit2 is a 1:1 mapping of the C library, so it is only concerned with wrapping the code that is already present in the libgit2 API. Gittyup, on the other hand, is a lot better place for this sort of improvements and I don't see any reason why missing functionality could not be added.

@fbpyr
Copy link
Contributor Author

fbpyr commented Sep 9, 2022

@haxscramper : thank you for the quick response - sounds good to me. 🙂
@disruptek : would you be interested having that functionality in gittyup?
iirc I somewhere saw a snippet recently that implemented pull with libgit2 functionality
(wrapped with nimgit2, but I guess that should work the same with hlibgit2).
I will dig for that snippet, maybe it can help with the implementation of pull in gittyup.

@disruptek
Copy link
Owner

If you produce a PR, I will be happy to merge it. We can refine it from there; it's new API, so it doesn't really matter how well it works, though the tests are far more important than the implementation.

The more trivial fetch functionality can be immediately adopted in nimph, since it currently farms out to git for that.

@disruptek disruptek added the enhancement New feature or request label Sep 9, 2022
@disruptek disruptek pinned this issue Sep 9, 2022
@disruptek disruptek reopened this Sep 9, 2022
@fbpyr
Copy link
Contributor Author

fbpyr commented Sep 9, 2022

I think as start, I would first post the snippet here -
as it might a bit crude and not using any of gittyup's
nice supporting functions.. 🤔

@fbe-work
Copy link
Contributor

import os
import nimgit2
import strformat
import strutils

type
  Repo = git_repository
  GitOId = git_oid
  GitTime = git_time_t
  StrArray = git_strarray
  GitReference = git_reference
  Commit = git_commit

func `$`*(oid: var GitOId): string =
  result = $git_oid_tostr_s(addr oid)

proc info(text: string) {.discardable.} =
  echo "[INFO] ", text

proc error(text: string) {.discardable.} =
  echo "[ERROR] ", text

proc reportResult(resultCode: int, resultName: string) {.discardable.} =
  if resultCode < 0:
    let lastErr = git_error_last()
    ($(lastErr.klass) & ": " & $(lastErr.message)).error
  else:
    # "success: {resultName}: {resultCode}".info
    return

proc getOidFromSha(sha: cstring): GitOId =
  reportResult(git_oid_fromstr(addr result, sha), "getOidFromSha")

proc getShaFromOid(oid: var GitOId): cstring =
  return git_oid_tostr_s(addr oid)

proc getCommitFromSha(repo: ptr Repo, sha: cstring): ptr Commit =
  var
    shaOid = getOidFromSha(sha)
    shaCommit: ptr git_commit
  let commitFromShaResult = git_commit_lookup(addr shaCommit, repo, addr shaOid)
  reportResult(commitFromShaResult, "commitFromShaResult")
  return shaCommit

proc report_merge_analysis(result: git_merge_analysis_t) =
  if   result == GIT_MERGE_ANALYSIS_NONE:        fmt"GIT_MERGE_ANALYSIS_NONE       : {GIT_MERGE_ANALYSIS_NONE}"       .info
  elif result == GIT_MERGE_ANALYSIS_NORMAL:      fmt"GIT_MERGE_ANALYSIS_NORMAL     : {GIT_MERGE_ANALYSIS_NORMAL}"     .info
  elif result == GIT_MERGE_ANALYSIS_UP_TO_DATE:  fmt"GIT_MERGE_ANALYSIS_UP_TO_DATE : {GIT_MERGE_ANALYSIS_UP_TO_DATE}" .info
  elif result == GIT_MERGE_ANALYSIS_FASTFORWARD: fmt"GIT_MERGE_ANALYSIS_FASTFORWARD: {GIT_MERGE_ANALYSIS_FASTFORWARD}".info
  elif result == GIT_MERGE_ANALYSIS_UNBORN:      fmt"GIT_MERGE_ANALYSIS_UNBORN     : {GIT_MERGE_ANALYSIS_NONE}"       .info
  fmt"GIT_MERGE_ANALYSIS: {result}".info

const
  repoPath = "/tmp/gittyup"
  branchName = "master"
  remoteName = "origin"
  url = "https://github.com/disruptek/gittyup"
  masterRef = "refs/remotes/origin/master"
  logMessage = "attempt to fetch / pull fast forward"
  refLogMessage = "fetch"
  theirHeadsLen = 1.cuint

let initResult = git_libgit2_init()
reportResult(initResult, "init_result")

var
  repo: ptr Repo
  repoHeadRef: ptr GitReference
  fetchOpts: git_fetch_options
  remote: ptr git_remote
  refSpecs: StrArray
  gitRef: ptr GitReference
  fetchAnnoCommit: ptr git_annotated_commit
  checkoutOpt: git_checkout_options
  mergeAnalysis: git_merge_analysis_t
  mergePreference: git_merge_preference_t
  newTargetRef: ptr GitReference

fmt"clone or pull of {url} at {repoPath}".info
if not repoPath.dir_exists():
  "repo does not exist yet: cloning..".info
  let cloneOpenResult = git_clone(addr repo, url, repoPath, nil)
  reportResult(cloneOpenResult, "cloneOpenResult")
else:
  "repo exists: opening..".info
  let openResult = git_repository_open(addr repo, repoPath)
  reportResult(openResult, "openResult")

let repoHeadRefResult = git_repository_head(addr repoHeadRef, repo)
reportResult(repoHeadRefResult, "repoHeadRefResult")

"fetching..".info
let optInitResult = git_fetch_options_init(addr fetchOpts, 1.cuint)
reportResult(optInitResult, "optInitResult")

let remoteResult = git_remote_lookup(addr remote, repo, remoteName)
reportResult(remoteResult, "remoteResult")

let fetchResult = git_remote_fetch(remote, addr refSpecs, addr fetchOpts, refLogMessage)
reportResult(fetchResult, "fetchResult")

let remoteMasterIdResult = git_reference_lookup(addr gitRef, repo, masterRef)
reportResult(remoteMasterIdResult, "remoteMasterIdResult")
let refTarget = git_reference_target(git_ref)

let fetchAnnoRes = git_annotated_commit_from_fetchhead(addr fetchAnnoCommit,
    repo, branchName, url, refTarget)
reportResult(fetchAnnoRes, "fetchAnnoRes")

let analyseResult = git_merge_analysis(addr mergeAnalysis, addr mergePreference,
    repo, addr fetchAnnoCommit, theirHeadsLen)

reportResult(analyseResult, "analyseResult")
reportMergeAnalysis(mergeAnalysis)

if   mergeAnalysis == GIT_MERGE_ANALYSIS_UP_TO_DATE:
  "nothing to do: UP_TO_DATE".info

elif mergeAnalysis == GIT_MERGE_ANALYSIS_FASTFORWARD:
  "WIP: GIT_MERGE_ANALYSIS_FASTFORWARD".info

elif mergeAnalysis == 5:
  "WIP: GIT_MERGE_ANALYSIS: NORMAL & FASTFORWARD".info

  var optRes = git_checkout_options_init(addr checkoutOpt, GIT_CHECKOUT_OPTIONS_VERSION)
  reportResult(optRes, "optRes")

  let remoteMasterId = getShaFromOid(ref_target[])
  fmt"{remoteMasterId =}".info

  let
    remoteMasterCommit = getCommitFromSha(repo, remoteMasterId)
    commitToObj = cast[ptr git_object](remoteMasterCommit)
    checkoutResult = git_checkout_tree(repo, commitToObj, addr checkoutOpt)
  reportResult(checkoutResult, "checkoutResult")

  let setTargetRes = git_reference_set_target(addr newTargetRef, repoHeadRef,
      refTarget, logMessage)
  reportResult(setTargetRes, "setTargetRes")

elif mergeAnalysis == GIT_MERGE_ANALYSIS_NORMAL:
  "WIP: GIT_MERGE_ANALYSIS_NORMAL".info

else:
  "WIP: other GIT_MERGE_ANALYSIS".info

let shutdownResult = git_libgit2_shutdown()
fmt"{shutdownResult =}".info

^^ this is the snippet @fbpyr mentioned.
I once wrote it for using it as autoupdater for some repos,
where it still works pretty well. No tests so far, though.

@fbpyr
Copy link
Contributor Author

fbpyr commented Sep 12, 2022

thank you @fbe-work - exactly. 🙂
I will have a look if I can produce some tests with it.

@disruptek
Copy link
Owner

Holy shit, someone is actually using gittyup.

@fbpyr
Copy link
Contributor Author

fbpyr commented Sep 13, 2022

@disruptek trying my first gittyup fetch test, I am wondering (sorry potentially noob question):
how can I use the modified local repo gittyup with the added fetch instead of the nimble-installed one for test.nim?

@disruptek
Copy link
Owner

You could use Nimph or Nimble with local dependencies mode, right?

With Nimph, nimph fork gittyup will create the fork for you and setup the remotes, etc. You could patch Nimph's fetch subcommand and that would kill two birds with one stone. 😁

@fbpyr
Copy link
Contributor Author

fbpyr commented Sep 13, 2022

that sounds ery useful! will try. thank you so much!

@disruptek disruptek linked a pull request Oct 12, 2022 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants