LOLINTERNETZ / vscodeoffline

Enables Visual Studio Code's extension gallery to be used in offline (air-gapped) environments. Or, run your own gallery!
https://hub.docker.com/u/lolinternet
MIT License
101 stars 31 forks source link

--syncall fetches pre-release versions and only insider version actually work. #31

Closed dev-ninja-ops closed 2 years ago

dev-ninja-ops commented 2 years ago

Hi,

When I use syncall (I need the entire market), I only get pre-release versions, which only works on the latest insider version of vscode. Is there a way to fetch only the stable releases of the entire market + its related stable vscode binary ?

EDIT: What I mean by it doesn't work is for instace if I install the stable version, and try to install a plugin than a pop up message appears stating the plugin is not compatible with the version installed.

Thanks,

Ebsan commented 2 years ago

I'm noticing this as well. For example, when using --syncall it will only grab pre-release version of extensions which can't be installed with the stable release of vscode.

@dev-ninja-ops did you find any workarounds?

tomer953 commented 2 years ago

It also relevant to --sync

I cannot install Python extension for example, since it fetched the pre-release version

tomer953 commented 2 years ago

Some information I found:

each version has properties (if you include the IncludeVersionProperties flag)

{
  "key": "Microsoft.VisualStudio.Code.PreRelease",
  "value": "true"
}

however, if we use the IncludeLatestVersionOnly we ended with the latest version even if its a pre-release one.

so or we could find a way to query only stable versions, or we need to remove this flag (which leads to low performence), and filter manually

also might be useful: https://github.com/microsoft/vscode/blob/main/src/vs/platform/extensionManagement/common/extensionGalleryService.ts#L203

tomer953 commented 2 years ago

Not going to PR this because I did not tested enough, but what I did is to disable the IncludeLatestVersionOnly from def _query_flags(self):

so I have:

    def _query_flags(self):
        return vsc.QueryFlags.IncludeFiles | vsc.QueryFlags.IncludeVersionProperties | vsc.QueryFlags.IncludeAssetUri | \
            vsc.QueryFlags.IncludeStatistics | vsc.QueryFlags.ExcludeNonValidated

then added this helper function to VSCExtensionDefinition class:

    def is_prerelease(self, version):
        if "properties" in version:
            for prop in version["properties"]:
                if prop["key"] == "Microsoft.VisualStudio.Code.PreRelease" and prop["value"] == "true":
                    return True
        return False

finally filter the versions to only stable one, by chaning the constructor def __init__(self, identity, raw=None):

to:

    def __init__(self, identity, raw=None):
        self.identity = identity
        self.extensionId = None
        self.recommended = False
        self.versions = []
        if raw:
            self.__dict__.update(raw)            
            if 'extensionId' in raw:
                self.extensionId = raw['extensionId']
        # take the first stable version
        stable_versions = [v for v in self.versions if not self.is_prerelease(v)]
        self.versions = [] if len(stable_versions) == 0 else [stable_versions[0]]

However, this query is a lot slower since it returns a big amount of versions, and not only the latest one - so I added some sleep function after the query..

    def search_by_extension_name(self, extensionname):
        result = self._query_marketplace(vsc.FilterType.ExtensionName, extensionname)
        time.sleep(0.2)

for the first try it looks like everything is working, but I really think the owner should take a look

vscsync_1     | [I 220728 17:41:46 sync:595] Checking and Downloading Updates for 584 Extensions
vscsync_1     | [I 220728 17:41:46 sync:600] Progress 0/584 (0.0%)
vscsync_1     | [I 220728 17:43:53 sync:600] Progress 100/584 (17.1%)
vscsync_1     | [I 220728 17:44:17 sync:600] Progress 200/584 (34.2%)
vscsync_1     | [I 220728 17:45:09 sync:600] Progress 300/584 (51.4%)
vscsync_1     | [I 220728 17:45:47 sync:600] Progress 400/584 (68.5%)
vscsync_1     | [I 220728 17:46:16 sync:600] Progress 500/584 (85.6%)
vscsync_1     | [I 220728 17:46:19 sync:611] Complete

also, this should be a an optional flag, maybe some users wants the pre-release extensions... but I agree that at least one stable extension is a must have.

Ebsan commented 2 years ago

I'm currently working on the PR with a similar solution to what you came up with. I'm adding a prerelease arg and some other things as well. Hope to be done for testing by today or tomorrow.

Ebsan commented 2 years ago

@LOLINTERNETZ , @tomer953 I just created the pull request #36. Please test if you can. I'm new to python so it may need some cleanup.

tomer953 commented 2 years ago

Thanks, for now Im testing my small change.

You should consider squash your commits into one or two max (ie: use requests instead of sessions + add flag for prerelease extensions) Before making a PR, just a general tip about PRs

LOLINTERNETZ commented 2 years ago

Thanks @Ebsan, @tomer953 and @dev-ninja-ops.

Looks like a great first PR and has just been merged just now. Honestly, while I've been a professional dev for a long time my Python is pretty poor at the best of times (🦀 represent), so this codebase is definitely not a shining example. Whenever I look at it irks me. As @tomer953 said, commits are all about meaning. If there's not a lot going on squash them, if there's a lot going on then separate them and consider multiple PRs. This PR touches a few things and is basically oriented toward fixing what was broken. This made things easier as I was able to work through all of your changes with one goal in mind - getting the functionality stable again, there were a few other things thrown in which is fine as their scope was small.

Always happy for reviews and your PRs in the future @Ebsan! Thanks again