webinstall / webi-roadmap

A space where we can ideate without cluttering the main repo with stale issues
Mozilla Public License 2.0
2 stars 0 forks source link

Feature: tagged versions for git repos #17

Closed coolaj86 closed 7 months ago

coolaj86 commented 1 year ago

Update: Confirmed

Not sure what I was looking at before, but the difference between these two looks right:

note: also useful: https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/

git ls-remote --tags https://github.com/jshint/jshint

Before:

Ascending Sort

--sort=version:refname

git -c 'versionsort.suffix=-' \
    ls-remote --tags --sort='version:refname' \
    https://github.com/jshint/jshint

After:

Descending Sort

--sort=-version:refname

git -c 'versionsort.suffix=-' \
    ls-remote --tags --sort='-version:refname' \
    https://github.com/jshint/jshint

After:

Release Type Comparison

Original

Most (all?) of the vim plugins are direct via Git (not GitHub, just git).

For anything that has a tagged git source we could switch to showing versions using git ls-remote:

git -c 'versionsort.suffix=-' \
    ls-remote --tags --sort='version:refname' \
    https://github.com/BeyondCodeBootcamp/aliasman
6a0ee1723b2106e117fc0f3862ca340eab8c26c5    refs/tags/v1.0.0
4171e2fe58122c61a100941c05ef963d80b413f4    refs/tags/v1.0.1

(doesn't seem sorted by version at all...)

This may include replacing the newly-added GitHub Source adapter, in most cases.

y0rune commented 1 year ago

As far I checked the sorted is working properly. If you would like to have the latest version You have to get a last line.

Example - unsorted:

$ git ls-remote --tags https://github.com/CiscoDevNet/ansible-meraki
b32050ef8ee889a52c4615fd22917af1cf13bb20    refs/tags/v0.0.1
2af39c5e301cea149f3c6d5cff2c275cd7149a48    refs/tags/v0.0.1^{}
eb56b8f51adddfd1f9434146e601cba784214a97    refs/tags/v0.1.0
85bed4cded64b1692f3f09ef60ed692781f0d26e    refs/tags/v0.1.1
1001804ccb94ded3f501b740b2962c52fef146ac    refs/tags/v1.0.0
6b2385bf22d6ec4037146cf874a84eb4d6831778    refs/tags/v1.0.1
32af9a3c7c0d78283d123355eb206e7b31ba678b    refs/tags/v1.0.2
7207ef0d563f48fef4757805620468ba9923e7d3    refs/tags/v1.1.0
fc458292a0efdd0a673e020a7cc14251b3ec00f3    refs/tags/v1.2.0
d3a15a9ceebfd5a30b8f2bad13e4a89124f3e02d    refs/tags/v1.3.0
8e1a1332add76aba511d60bfa924ad02fb56c4fc    refs/tags/v1.3.1
e79ccff07014bd902e1c2a97cebd01e1639227bd    refs/tags/v1.3.2
29a041568cfbc07e495e65d4a4e2a2ff426636b7    refs/tags/v1.4.0
74e78e25db651415852f7f98b23c3bd841440208    refs/tags/v2.0.0
3b3d0fb2bcf11ba29303b839bfa4958c5a6854f2    refs/tags/v2.1.0
864046401a9ad7467905bcc77d84d79efe421c45    refs/tags/v2.1.1
433f5efc2c2d5e4db432a4558b611e2fb1cace3c    refs/tags/v2.1.2
b779f6254489587bb8c3e8e4977495be1e54fb04    refs/tags/v2.1.3
4c785c64ad5a834ac2d2ab7918846fc17aedd2fa    refs/tags/v2.10.0
65c58d23075ee078b76dc9c8724624d4de4e8c26    refs/tags/v2.10.1
33604da6efa35ce4e0f4a83f2880345618b16171    refs/tags/v2.11.0
56a154b40b7382f8b62417c27c0314c0b2a34481    refs/tags/v2.12.0
eb75cf034ec8eb7ec0b31887def670d6d4f1e383    refs/tags/v2.13.0
5b1d2b7fc6ffd4da23f68378c0c9335e32af7278    refs/tags/v2.14.0
3b248695e5bb02a705695fd0f8c3a8dc1009de2e    refs/tags/v2.15.0
eb85b374d59951dad30e131746e15e9f726d9f13    refs/tags/v2.15.1
841da8e54e0a7afd7c517c3df37ec00b7634f3a4    refs/tags/v2.2.0
d53c402dfd078ece9fd8dafd4b6554933cd25461    refs/tags/v2.2.1
d9219d7cb623fc466ec2fce7b2dffb9e18021ad5    refs/tags/v2.3.0
afa5a4c45158fba2171f6339a74c33e50a686075    refs/tags/v2.3.1
5b92bb264df9bbddb5911cef05ca242f8d3a2ef3    refs/tags/v2.4.0
3e09ed726a25f6f56e12ef90d5af3b5c1295129a    refs/tags/v2.4.2
dd670c3e62c6fd2a907147a72f1156949d8214ad    refs/tags/v2.5.0
50162b8fced161ae4cd9240cc8b2bffe1404038b    refs/tags/v2.6.0
b49a90872ffd690e34eebf2fb3eb933afd931daf    refs/tags/v2.6.1
eb1c195014b877032bdc7a42107fbbee7c219de0    refs/tags/v2.6.2
69172f2c1eca73f579f16b350f6acec327437d8c    refs/tags/v2.7.0
8e2305de13796161faa06806651ed54af1b56092    refs/tags/v2.8.0
45d2a9ab90ab266c065e3dc4eff8d3edeaee70e3    refs/tags/v2.9.0

Example sorted with your code:

$ git -c 'versionsort.suffix=-' ls-remote --tags --sort='v:refname' https://github.com/CiscoDevNet/ansible-meraki
b32050ef8ee889a52c4615fd22917af1cf13bb20    refs/tags/v0.0.1
2af39c5e301cea149f3c6d5cff2c275cd7149a48    refs/tags/v0.0.1^{}
eb56b8f51adddfd1f9434146e601cba784214a97    refs/tags/v0.1.0
85bed4cded64b1692f3f09ef60ed692781f0d26e    refs/tags/v0.1.1
1001804ccb94ded3f501b740b2962c52fef146ac    refs/tags/v1.0.0
6b2385bf22d6ec4037146cf874a84eb4d6831778    refs/tags/v1.0.1
32af9a3c7c0d78283d123355eb206e7b31ba678b    refs/tags/v1.0.2
7207ef0d563f48fef4757805620468ba9923e7d3    refs/tags/v1.1.0
fc458292a0efdd0a673e020a7cc14251b3ec00f3    refs/tags/v1.2.0
d3a15a9ceebfd5a30b8f2bad13e4a89124f3e02d    refs/tags/v1.3.0
8e1a1332add76aba511d60bfa924ad02fb56c4fc    refs/tags/v1.3.1
e79ccff07014bd902e1c2a97cebd01e1639227bd    refs/tags/v1.3.2
29a041568cfbc07e495e65d4a4e2a2ff426636b7    refs/tags/v1.4.0
74e78e25db651415852f7f98b23c3bd841440208    refs/tags/v2.0.0
3b3d0fb2bcf11ba29303b839bfa4958c5a6854f2    refs/tags/v2.1.0
864046401a9ad7467905bcc77d84d79efe421c45    refs/tags/v2.1.1
433f5efc2c2d5e4db432a4558b611e2fb1cace3c    refs/tags/v2.1.2
b779f6254489587bb8c3e8e4977495be1e54fb04    refs/tags/v2.1.3
841da8e54e0a7afd7c517c3df37ec00b7634f3a4    refs/tags/v2.2.0
d53c402dfd078ece9fd8dafd4b6554933cd25461    refs/tags/v2.2.1
d9219d7cb623fc466ec2fce7b2dffb9e18021ad5    refs/tags/v2.3.0
afa5a4c45158fba2171f6339a74c33e50a686075    refs/tags/v2.3.1
5b92bb264df9bbddb5911cef05ca242f8d3a2ef3    refs/tags/v2.4.0
3e09ed726a25f6f56e12ef90d5af3b5c1295129a    refs/tags/v2.4.2
dd670c3e62c6fd2a907147a72f1156949d8214ad    refs/tags/v2.5.0
50162b8fced161ae4cd9240cc8b2bffe1404038b    refs/tags/v2.6.0
b49a90872ffd690e34eebf2fb3eb933afd931daf    refs/tags/v2.6.1
eb1c195014b877032bdc7a42107fbbee7c219de0    refs/tags/v2.6.2
69172f2c1eca73f579f16b350f6acec327437d8c    refs/tags/v2.7.0
8e2305de13796161faa06806651ed54af1b56092    refs/tags/v2.8.0
45d2a9ab90ab266c065e3dc4eff8d3edeaee70e3    refs/tags/v2.9.0
4c785c64ad5a834ac2d2ab7918846fc17aedd2fa    refs/tags/v2.10.0
65c58d23075ee078b76dc9c8724624d4de4e8c26    refs/tags/v2.10.1
33604da6efa35ce4e0f4a83f2880345618b16171    refs/tags/v2.11.0
56a154b40b7382f8b62417c27c0314c0b2a34481    refs/tags/v2.12.0
eb75cf034ec8eb7ec0b31887def670d6d4f1e383    refs/tags/v2.13.0
5b1d2b7fc6ffd4da23f68378c0c9335e32af7278    refs/tags/v2.14.0
3b248695e5bb02a705695fd0f8c3a8dc1009de2e    refs/tags/v2.15.0
eb85b374d59951dad30e131746e15e9f726d9f13    refs/tags/v2.15.1

To sum up if you would like to have the latest commit tag (source link)

git -c 'versionsort.suffix=-' ls-remote --tags --sort='v:refname' https://github.com/CiscoDevNet/ansible-meraki | tail -n1 | sed 's/.*\///; s/\^{}//'
v2.15.1
coolaj86 commented 1 year ago

but the documented order said that it sorts DESCENDING. That's sorting ASCENDING. That's why I'm confused.

y0rune commented 1 year ago

The docs said: Prefix - to sort in descending order of the value. - (source).

So by default the sort is working in ascending order.

Examples

That examples work when the

Set the sort order

I have found the information that you can specific the default way. Setting the descending order by default:

git config --global 'versionsort.suffix' '-'
y0rune commented 1 year ago

Hello! I tried to implemented it in the one of the vim plugin. I chose the vim-ale as a example. Is it a good way to do it like here: https://github.com/webinstall/webi-installers/pull/566? Can you check it @coolaj86?

coolaj86 commented 1 year ago

Checked and commented.

coolaj86 commented 8 months ago

I'd like to get the date as well, but a bare, single-branch shallow clone is still way too large:

git clone https://github.com/jshint/jshint --bare --depth=1 --single-branch --branch 2.13.6
Cloning into bare repository 'jshint.git'...
remote: Enumerating objects: 234, done.
remote: Counting objects: 100% (234/234), done.
remote: Compressing objects: 100% (215/215), done.
remote: Total 234 (delta 3), reused 155 (delta 2), pack-reused 0
Receiving objects: 100% (234/234), 1.95 MiB | 4.65 MiB/s, done.
Resolving deltas: 100% (3/3), done.
coolaj86 commented 8 months ago

Getting a "treeless" clone that contains only the commit data may work, since we only need it once and can get data about every commit from there:

git clone https://github.com/jshint/jshint --filter=tree:0 --bare
Cloning into bare repository 'jshint.git'...
remote: Enumerating objects: 4635, done.
remote: Total 4635 (delta 0), reused 0 (delta 0), pack-reused 4635
Receiving objects: 100% (4635/4635), 1.15 MiB | 2.96 MiB/s, done.
Resolving deltas: 100% (25/25), done.
pushd ./jshint.git/
git log
commit 6d06f8f8fccc0b89a54bfe58af83a54bc1fae414
Author: Mike Pennisi
Date:   Fri Nov 11 14:06:50 2022 -0500

    v2.13.6

......

commit 42ace75af50335e83e7ea8ab5d50b470489051e0
Author: Anton Kovalyov
Date:   Wed Jan 30 11:07:39 2013 -0800

    1.0.0 release
coolaj86 commented 8 months ago

I asked GPT to create the boilerplate for me:

const util = require('util');
const exec = util.promisify(require('child_process').exec);
const fs = require('fs').promises;

const repo = "https://github.com/jshint/jshint";
const repoName = repo.split('/').pop();
const repoPath = `/mnt/repos/${repoName}`;

// Function to clone the repository if it doesn't exist
async function cloneRepository() {
  if (!await repoExists()) {
    await exec(`git clone --bare ${repo} ${repoPath}`);
  }
}

// Function to check if the repository already exists
async function repoExists() {
  try {
    await fs.access(repoPath);
    return true;
  } catch (error) {
    return false;
  }
}

// Function to list all version tags
async function listVersionTags() {
  await cloneRepository();
  const { stdout } = await exec(`git --git-dir=${repoPath} tag`);
  const tags = stdout.trim().split('\n');
  return tags;
}

// Function to create an array of release info objects
async function createReleaseInfo() {
  const tags = await listVersionTags();
  const releaseInfo = [];

  for (const tag of tags) {
    const { stdout: tagDate } = await exec(`git --git-dir=${repoPath} log -1 --format=%ad --date=iso ${tag}`);
    const tagObject = {
      name: `${repoName}-v${tag}`,
      tag,
      date: tagDate.trim(),
      ext: 'git',
      command: `git clone --depth=1 --single-branch --branch ${tag} ${repo}`,
    };
    releaseInfo.push(tagObject);
  }

  return releaseInfo;
}

// Example usage with async/await:
(async () => {
  const releaseInfoArray = await createReleaseInfo();
  console.log(releaseInfoArray);
})();

(I'll go test and massage that now)

coolaj86 commented 8 months ago

For the record, here's the difference between what it gave me and what I needed - mostly just boilerplate and cosmetic:

diff --git a/_common/git-gpt.js b/_common/git-gpt.js
index 7326c8e..ba47464 100644
--- a/_common/git-gpt.js
+++ b/_common/git-gpt.js
@@ -1,15 +1,37 @@
+'use strict';
+
+require('dotenv').config({ path: '.env' });
+if (!process.env.REPO_BASE_DIR) {
+  console.warn('[Warn] REPO_BASE_DIR= not set, using ./repos/');
+}
+// ../ because this script is one directory deep
+let repoBaseDir = process.env.REPO_BASE_DIR || '../repos';
+
 const util = require('util');
 const exec = util.promisify(require('child_process').exec);
 const fs = require('fs').promises;

-const repo = "https://github.com/jshint/jshint";
-const repoName = repo.split('/').pop();
-const repoPath = `/mnt/repos/${repoName}`;
+/**
+ * Lists GitHub Releases (w/ uploaded assets)
+ *
+ * @param request
+ * @param {string} owner
+ * @param {string} gitUrl
+ * @returns {PromiseLike<any> | Promise<any>}
+ */
+async function getAllReleases(gitUrl) {
+  const all = {
+    releases: [],
+    download: ''
+  };
+
+  const repoName = gitUrl.split('/').pop();
+  const repoPath = `${repoBaseDir}/${repoName}`;

   // Function to clone the repository if it doesn't exist
   async function cloneRepository() {
-  if (!await repoExists()) {
-    await exec(`git clone --bare ${repo} ${repoPath}`);
+    if (!(await repoExists())) {
+      await exec(`git clone --bare ${gitUrl} ${repoPath}`);
     }
   }

@@ -37,13 +59,15 @@ async function createReleaseInfo() {
     const releaseInfo = [];

     for (const tag of tags) {
-    const { stdout: tagDate } = await exec(`git --git-dir=${repoPath} log -1 --format=%ad --date=iso ${tag}`);
+      const { stdout: tagDate } = await exec(
+        `git --git-dir=${repoPath} log -1 --format=%ad --date=iso ${tag}`
+      );
       const tagObject = {
         name: `${repoName}-v${tag}`,
-      tag,
+        version: tag,
         date: tagDate.trim(),
         ext: 'git',
-      command: `git clone --depth=1 --single-branch --branch ${tag} ${repo}`,
+        command: `git clone --depth=1 --single-branch --branch ${tag} ${gitUrl}`
       };
       releaseInfo.push(tagObject);
     }
@@ -51,8 +75,23 @@ async function createReleaseInfo() {
     return releaseInfo;
   }

-// Example usage with async/await:
-(async () => {
-  const releaseInfoArray = await createReleaseInfo();
-  console.log(releaseInfoArray);
-})();
+  all.releases = await createReleaseInfo();
+
+  return all;
+}
+module.exports = getAllReleases;
+
+if (module === require.main) {
+  (async function main() {
+    let all = await getAllReleases('https://github.com/jshint/jshint');
+    console.log(all.releases[0]);
+    all = require('../_webi/normalize.js')(all);
+    console.info(JSON.stringify(all, null, 2));
+  })()
+    .then(function () {
+      process.exit(0);
+    })
+    .catch(function (err) {
+      console.error(err);
+    });
+}
coolaj86 commented 7 months ago

Closed via #718