<gh_stars>10-100
import os
import subprocess
import sys
import io
import shutil
import json

import django

from port.models import LastPortIndexUpdate
import config
from settings import BASE_DIR

sys.path.append(BASE_DIR)
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")

django.setup()


def rebuild_repo(directory, url, name):
    # remove the existing repo directory, if available
    if os.path.isdir(directory):
        shutil.rmtree(url)

    # cd into the data directory
    os.chdir(config.DATA_DIR)

    # clone the repo
    subprocess.run([config.GIT, 'clone', '--quiet', url, name])


def refresh_portindex_json():
    # check if the contrib repo is available
    if not os.path.isdir(config.MACPORTS_CONTRIB_DIR):
        rebuild_repo(config.MACPORTS_CONTRIB_DIR, config.MACPORTS_CONTRIB_URL, config.MACPORTS_CONTRIB)

    # cd into the contrib repo
    os.chdir(config.MACPORTS_CONTRIB_DIR)

    # update the contrib repo
    subprocess.call([config.GIT, 'pull', '--quiet'])

    # go back
    os.chdir("..")

    # check if the ports repo is available
    if not os.path.isdir(config.MACPORTS_PORTS_DIR):
        rebuild_repo(config.MACPORTS_PORTS_DIR, config.MACPORTS_PORTS_URL, config.MACPORTS_PORTS)

    # cd into ports directory
    os.chdir(config.MACPORTS_PORTS_DIR)

    # update the ports repo
    subprocess.call([config.GIT, 'pull', '--quiet'])
    latest_commit = subprocess.run([config.GIT, 'rev-parse', 'HEAD'], stdout=subprocess.PIPE).stdout.decode('utf-8')

    # update/generate the portindex
    subprocess.run(['portindex', '-p', 'macosx_19_i386', '-x'])

    # update/generate portindex.json
    portindexjson = subprocess.run([config.TCLSH, config.PORTINDEX2JSON, config.LOCAL_PORTINDEX, '--info', 'commit={}'.format(latest_commit)], stdout=subprocess.PIPE).stdout.decode('utf-8')
    portindexjson = json.loads(portindexjson)
    with open(config.LOCAL_PORTINDEX_JSON, 'w') as file:
        json.dump(portindexjson, file)

    # match the latest commit from the repo and the portindex.json match
    if latest_commit != portindexjson.get('info', {}).get('commit'):
        # if they don't match, we should abort the operation
        raise KeyError

    return latest_commit


def get_old_commit():
    # first search in database
    old_commit_obj = LastPortIndexUpdate.objects.all().first()
    if old_commit_obj is None:
        old_commit = None
    else:
        old_commit = old_commit_obj.git_commit_hash

    return old_commit


def get_updated_portdirs():
    # update portindex.json and get new commit
    new_commit = refresh_portindex_json()
    old_commit = get_old_commit()

    # cd into the ports repository
    os.chdir(config.MACPORTS_PORTS_DIR)

    # generate the range of commits to find updated paths
    range_commits = str(old_commit).strip() + "^.." + str(new_commit).strip()

    changed_paths = subprocess.run([config.GIT, 'diff', '--name-only', range_commits], stdout=subprocess.PIPE).stdout.decode('utf-8')
    s = io.StringIO(changed_paths)
    updated_ports_dir = set()

    # loop over all the paths and find portdirs to update
    for line in s:
        sections = line.split('/')
        if len(sections) < 2:
            # ignore updates in the root directory
            continue
        portdir = sections[0].lower() + '/' + sections[1].lower()
        updated_ports_dir.add(portdir)

    os.chdir(BASE_DIR)
    return updated_ports_dir


def get_portindex_json():
    if os.path.isfile(config.LOCAL_PORTINDEX_JSON):
        with open(config.LOCAL_PORTINDEX_JSON, "r", encoding='utf-8') as file:
            try:
                data = json.load(file)
            except json.decoder.JSONDecodeError:
                data = None
        return data
    else:
        return None

import os
import subprocess
import sys
import io
import shutil
import json

import django

from port.models import LastPortIndexUpdate
import config
from settings import BASE_DIR

sys.path.append(BASE_DIR)
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")

django.setup()


def rebuild_repo(directory, url, name):
    # remove the existing repo directory, if available
    if os.path.isdir(directory):
        shutil.rmtree(url)

    # cd into the data directory
    os.chdir(config.DATA_DIR)

    # clone the repo
    subprocess.run([config.GIT, 'clone', '--quiet', url, name])


def refresh_portindex_json():
    # check if the contrib repo is available
    if not os.path.isdir(config.MACPORTS_CONTRIB_DIR):
        rebuild_repo(config.MACPORTS_CONTRIB_DIR, config.MACPORTS_CONTRIB_URL, config.MACPORTS_CONTRIB)

    # cd into the contrib repo
    os.chdir(config.MACPORTS_CONTRIB_DIR)

    # update the contrib repo
    subprocess.call([config.GIT, 'pull', '--quiet'])

    # go back
    os.chdir("..")

    # check if the ports repo is available
    if not os.path.isdir(config.MACPORTS_PORTS_DIR):
        rebuild_repo(config.MACPORTS_PORTS_DIR, config.MACPORTS_PORTS_URL, config.MACPORTS_PORTS)

    # cd into ports directory
    os.chdir(config.MACPORTS_PORTS_DIR)

    # update the ports repo
    subprocess.call([config.GIT, 'pull', '--quiet'])
    latest_commit = subprocess.run([config.GIT, 'rev-parse', 'HEAD'], stdout=subprocess.PIPE).stdout.decode('utf-8')

    # update/generate the portindex
    subprocess.run(['portindex', '-p', 'macosx_19_i386', '-x'])

    # update/generate portindex.json
    portindexjson = subprocess.run([config.TCLSH, config.PORTINDEX2JSON, config.LOCAL_PORTINDEX, '--info', 'commit={}'.format(latest_commit)], stdout=subprocess.PIPE).stdout.decode('utf-8')
    portindexjson = json.loads(portindexjson)
    with open(config.LOCAL_PORTINDEX_JSON, 'w') as file:
        json.dump(portindexjson, file)

    # match the latest commit from the repo and the portindex.json match
    if latest_commit != portindexjson.get('info', {}).get('commit'):
        # if they don't match, we should abort the operation
        raise KeyError

    return latest_commit


def get_old_commit():
    # first search in database
    old_commit_obj = LastPortIndexUpdate.objects.all().first()
    if old_commit_obj is None:
        old_commit = None
    else:
        old_commit = old_commit_obj.git_commit_hash

    return old_commit


def get_updated_portdirs():
    # update portindex.json and get new commit
    new_commit = refresh_portindex_json()
    old_commit = get_old_commit()

    # cd into the ports repository
    os.chdir(config.MACPORTS_PORTS_DIR)

    # generate the range of commits to find updated paths
    range_commits = str(old_commit).strip() + "^.." + str(new_commit).strip()

    changed_paths = subprocess.run([config.GIT, 'diff', '--name-only', range_commits], stdout=subprocess.PIPE).stdout.decode('utf-8')
    s = io.StringIO(changed_paths)
    updated_ports_dir = set()

    # loop over all the paths and find portdirs to update
    for line in s:
        sections = line.split('/')
        if len(sections) < 2:
            # ignore updates in the root directory
            continue
        portdir = sections[0].lower() + '/' + sections[1].lower()
        updated_ports_dir.add(portdir)

    os.chdir(BASE_DIR)
    return updated_ports_dir


def get_portindex_json():
    if os.path.isfile(config.LOCAL_PORTINDEX_JSON):
        with open(config.LOCAL_PORTINDEX_JSON, "r", encoding='utf-8') as file:
            try:
                data = json.load(file)
            except json.decoder.JSONDecodeError:
                data = None
        return data
    else:
        return None
# remove the existing repo directory, if available # cd into the data directory # clone the repo # check if the contrib repo is available # cd into the contrib repo # update the contrib repo # go back # check if the ports repo is available # cd into ports directory # update the ports repo # update/generate the portindex # update/generate portindex.json # match the latest commit from the repo and the portindex.json match # if they don't match, we should abort the operation # first search in database # update portindex.json and get new commit # cd into the ports repository # generate the range of commits to find updated paths # loop over all the paths and find portdirs to update # ignore updates in the root directory