Scoop icon indicating copy to clipboard operation
Scoop copied to clipboard

[Feature] Use LibGit2Sharp instead of installing whole Git

Open couleurm opened this issue 3 years ago β€’ 19 comments

Feature Request

Is your feature request related to a problem? Please describe.

Scoop looses a bit of it's magic if you don't install git (buckets, updates, etc..)

Describe the solution you'd like

Why not use LibGit2Sharp? It lets you clone repositories with PowerShell while it's only a few hundred kilobytes. I'm not sure about if it can pull / show new commits but I doubt it'd need to be that bigger. Because of it's small size it could come with the scoop installer and let people easily add other buckets

Describe alternatives you've considered

None other I can think of

couleurm avatar Apr 18 '22 17:04 couleurm

It's a nice idea, but can the library show git logs and style them like we do currently?

rashil2000 avatar Apr 19 '22 01:04 rashil2000

Marked and MAY adopt this idea, thanks!

niheaven avatar Apr 19 '22 10:04 niheaven

Removing the dependency of 7zip would be nice too, but https://github.com/thoemmi/7Zip4Powershell uses 7z.dll, and I recall that 7z.dll doesn't have all the functionality we need of 7zip.exe. I think it was that expanding .exe's required 7z.exe, but I'm not sure.

rasa avatar Apr 19 '22 13:04 rasa

Well, I actually tried that before 😁 https://github.com/ScoopInstaller/GitCloner/blob/master/src/gitcloner.ps1

It seems to support git log. https://github.com/libgit2/libgit2sharp/wiki/git-log https://github.com/libgit2/libgit2sharp/wiki/git-log-name-status

r15ch13 avatar Apr 19 '22 14:04 r15ch13

Well, I actually tried that before 😁 https://github.com/ScoopInstaller/GitCloner/blob/master/src/gitcloner.ps1

It seems to support git log. https://github.com/libgit2/libgit2sharp/wiki/git-log https://github.com/libgit2/libgit2sharp/wiki/git-log-name-status

Did you encounter any issues that stopped you from implementing git-cloner to scoop?

couleurm avatar Apr 19 '22 15:04 couleurm

Probably the log issue. Don't know anymore πŸ˜„ Currently trying to implement the logging. (Failing to get the x minutes/hours ago part with the correct values)

r15ch13 avatar Apr 20 '22 17:04 r15ch13

Currently trying to implement the logging

I'll keep an eye on ScoopInstaller/GitCloner thank you πŸ‘€πŸ‘€

couleurm avatar Apr 20 '22 17:04 couleurm

So this is what I came up with. But there might be a license problem, because I based the ConvertTo-RelativeDate-Function on the show_date_relative() from Git itself. (I don't know if the GPL-2.0 allows us to do that. Γ°ΒŸΒ€Β·Γ°ΒŸΒΒ½Γ’Β€ΒΓ’Β™Β‚Γ―ΒΈΒ)

The output is the same as git --no-pager log --no-decorate --format='tformat: * %C(yellow)%h%Creset %<|(72,trunc)%s %C(cyan)%cr%Creset' '$previousCommit..HEAD'. Some commits get switched if they are commited at the exact same second. (not a problem)

<#
.SYNOPSIS
    Shows the git log from a past commit hash to HEAD
.DESCRIPTION
    A small script shows the git log from a given commit hash to the current HEAD
.PARAMETER Repository
    Valid path to local Git repository
.PARAMETER StartHash
    The commit hash uses to create the log '$hash..HEAD'
.PARAMETER Color
    Switch for colored output
.EXAMPLE
    PS > .\gitlogger.ps1 -Repository '~/scoop/bucket/main' -StartHash "2d09f7c00" -Color
#>
param (
    [Parameter(Mandatory = $true, Position = 0)]
    [ValidateScript( {
        if (!(Test-Path $_ -Type Container)) {
            throw "$_ is not a directory!"
        } else {
            $true
        }
    })]
    [String] $Repository,
    [Parameter(Mandatory = $true, Position = 1)]
    [String] $StartHash = "",
    [Switch] $Color
)

Add-Type -TypeDefinition @"
    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;

    public static class Kernel32
    {
        [DllImport("kernel32", SetLastError=true, CharSet = CharSet.Ansi)]
        public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
    }
"@


if([System.IntPtr]::Size -eq 8) {
    [Kernel32]::LoadLibrary((Get-ChildItem "$PSScriptRoot\lib\win32\x64\git2-???????.dll" | Select-Object -First 1).FullName) | Out-Null
} else {
    [Kernel32]::LoadLibrary((Get-ChildItem "$PSScriptRoot\lib\win32\x86\git2-???????.dll" | Select-Object -First 1).FullName) | Out-Null
}

Add-Type -Path "$PSScriptRoot\LibGit2Sharp.dll"

function ConvertTo-PluralizedString {
    [OutputType([String])]
    param (
        [Parameter(Mandatory = $true)]
        [Int]
        $Value,
        [Parameter(Mandatory = $true)]
        [String]
        $Singular,
        [Parameter(Mandatory = $true)]
        [String]
        $Plural
    )
    if($Value -gt 1) {
        return $Plural -f $Value
    }
    return $Singular -f $Value
}

# Based on https://github.com/git/git/blob/master/date.c
function ConvertTo-RelativeDate {
    [OutputType([String])]
    param (
        [Parameter(Mandatory = $true, Position = 1)]
        [DateTimeOffset]
        $Date
    )

    $ts = New-TimeSpan -Start $Date.LocalDateTime.Ticks
    $diff = $ts.TotalSeconds

    if($diff -lt 0) {
        return "in the future"
    }

    # Turn it into minutes
    $diff = ($diff + 30) / 60;
    if($diff -lt 90) {
        return ConvertTo-PluralizedString -Singular "{0} minute ago" -Plural "{0} minutes ago" -Value ([int][Math]::Floor($diff))
    }

    # Turn it into hours
    $diff = ($diff + 30) / 60;
    if ($diff -lt 36) {
        return ConvertTo-PluralizedString -Singular "{0} hour ago" -Plural "{0} hours ago" -Value ([int][Math]::Floor($diff))
    }

    # We deal with number of days from here on
    $diff = ($diff + 12) / 24;
    if ($diff -lt 14) {
        return ConvertTo-PluralizedString -Singular "{0} day ago" -Plural "{0} days ago" -Value ([int][Math]::Floor($diff))
    }

    # Say weeks for the past 10 weeks or so
    if ($diff -lt 70) {
        return ConvertTo-PluralizedString -Singular "{0} week ago" -Plural "{0} weeks ago" -Value ([int][Math]::Floor(($diff + 3) / 7))
    }

    # Say months for the past 12 months or so
    if ($diff -lt 365) {
        return ConvertTo-PluralizedString -Singular "{0} month ago" -Plural "{0} months ago" -Value ([int][Math]::Floor(($diff + 15) / 30))
    }

    # Give years and months for 5 years or so
    if ($diff -lt 1825) {
        $totalmonths = ([int][Math]::Floor($diff) * 12 * 2 + 365) / (365 * 2);
        $years = [int][Math]::Floor($totalmonths / 12);
        $months = [int][Math]::Floor($totalmonths % 12);
        if ($months) {
            $sb = ConvertTo-PluralizedString -Singular "{0} year" -Plural "{0} years" -Value $years
            # TRANSLATORS: "%s" is "<n> years"
            return ConvertTo-PluralizedString -Singular "$sb, {0} month ago" -Plural "$sb, {0} months ago" -Value $months
        } else {
            return ConvertTo-PluralizedString -Singular "{0} year ago" -Plural "{0} years ago" -Value $years
        }
    }

    # Otherwise, just years. Centuries is probably overkill.
    return ConvertTo-PluralizedString -Singular "{0} year ago" -Plural "{0} years ago" -Value ([int][Math]::Floor(($diff + 183) / 365))
}

$repo = New-Object -TypeName LibGit2Sharp.Repository -ArgumentList $Repository
$properties = @{
    IncludeReachableFrom = 'HEAD';
}
if($StartHash.Length -gt 0) {
    $properties.ExcludeReachableFrom = $StartHash
}
$filter = New-Object -TypeName LibGit2Sharp.CommitFilter -Property $properties

# Recreates the following 'git log' command
# git --no-pager log --no-decorate --format='tformat: * %C(yellow)%h%Creset %<|(72,trunc)%s %C(cyan)%cr%Creset' '$previousCommit..HEAD'
try {
    if(!$Color) {
        $repo.Commits.QueryBy($filter) | ForEach-Object {
            $msg = $_.MessageShort.Trim().PadRight(59)
            if($msg.Length -gt 59) {
                $msg = "{0}.." -f $msg.Substring(0, 57)
            }
            $row = " * {0} {1} {2}" -f $_.Sha.Substring(0, 9), $msg, (ConvertTo-RelativeDate -Date $_.Author.When)
            Write-Output $row
        }
    } else {
        $repo.Commits.QueryBy($filter) | ForEach-Object {
            $msg = $_.MessageShort.Trim().PadRight(59)
            if($msg.Length -gt 59) {
                $msg = "{0}.." -f $msg.Substring(0, 57)
            }
            Write-Host -NoNewline " * "
            Write-Host -NoNewline -ForegroundColor DarkYellow $_.Sha.Substring(0, 9)
            Write-Host -NoNewline " $msg "
            Write-Host -ForegroundColor DarkCyan (ConvertTo-RelativeDate -Date $_.Author.When)
        }
    }
} catch [Exception] {
    Write-Output $_.Exception.Message
}

r15ch13 avatar Apr 20 '22 20:04 r15ch13

Using LibGit2Sharp would greatly accelerate installation speed, unzipping the main bucket is soo long..

couleurm avatar May 04 '22 07:05 couleurm

I like the overall idea. Just a word of warning: LibGit2Sharp has been lacking a maintainer for a couple of years. That doesn't need to be a blocker, but you should weigh it into the overall effort of implementing this issue, since you may have to maintain your own fork.

miniyou avatar Jun 21 '22 06:06 miniyou

Would be also cool if we used a DLL for 7-Zip (7z.dll) (if possible), since there's already DLLs in Scoop

couleurm avatar Oct 20 '22 15:10 couleurm

Will be, maybe in a 'plugins' feature.

niheaven avatar Oct 21 '22 11:10 niheaven

Another possible solution: Reducing MinGit to just git.exe , git-remote-https.exe, *.dll, license, ca-certs, and hook templates. Results in a ~8 MB ZIP or ~16 MB on disk.

image

r15ch13 avatar Feb 18 '23 18:02 r15ch13

yeah i dont think mingw is needed

though having this means as git in PATH could conflict with a real git..?

couleurm avatar Feb 18 '23 20:02 couleurm

What you see above is without mingw, but the DLLs are required to run git.exe. I just copied the DLLs over bit by bit until git.exe started working (in Windows Sandbox) :smile: This version of git would only be used internally without exposing it to the user environment.

r15ch13 avatar Feb 18 '23 21:02 r15ch13

great! that should help cut down the installation setup time πŸ‘πŸ‘ (i mean git isn't installed right at setup but still is a core part of scoop)

couleurm avatar Feb 19 '23 09:02 couleurm

great! that should help cut down the installation setup time πŸ‘πŸ‘

That should be fixed now btw, because of https://github.com/ScoopInstaller/Install/pull/42

rashil2000 avatar Feb 19 '23 13:02 rashil2000

git for scoop is around 350MB (mingw64 being 150MB of it). Has there been any outcome out of this libgit2 effort lately?

i2 avatar Jun 01 '23 12:06 i2

copying over from duplicate discussion.

  • i created this discussion as i was not actively aware of any small implementations of git for windows,
  • but here there are many.
  • so, switching to fossil would be more of a hack if there are not much additional benefits to it.
  • but i don't know, as i have never used that; and never dived beneath the surface of git either.

continuing from here: https://github.com/ScoopInstaller/Scoop/discussions/5885

so, on the client's win 7 system, using extras/doublecmd application, i navigated to the scoop-apps directory, and the git-portable or whatever was at the top consuming whopping 3xx MB of space.

this is whopping due to following reasons:

  • as that system is old and constrained on disk space.
  • for non-tech people who do not use git, this is way too much of a consumption by a needless superfluous application

so, i'd like to explore using main/fossil vcs for pulling the git buckets. it was only 30-40 MB the last time i used that. and it says that it can work with git. but i don't know if it can work with remote-gits too...

upside:

  • uses sqlite db to store git info, so, the database might very well be used directly lol

downside:

  • would still need to extract/use only dlls etc,
  • since fossil has lots of other stuff (like issue tracker, wiki, browser GUI, etc) beside just the "git-like" part.

versions

$ scoop --version | head -n2
Current Scoop version:
v0.3.1 - Released at 2022-11-15

$ scoop info fossil


Name        : fossil
Description : A simple, high-reliability, distributed software configuration management system.
Version     : 2.23
Bucket      : main
Website     : https://www.fossil-scm.org
License     : BSD-2-Clause
Updated at  : 2023-11-02 01:54:26
Updated by  : github-actions[bot]
Binaries    : fossil.exe


goyalyashpal avatar Apr 12 '24 16:04 goyalyashpal