def synced(self, branch=geogig.HEAD, credentials=None): ''' Returns a tuple with number of (ahead, behind) commits between this repo and a remote It uses the passed branch or, if not passed, the current branch If the repository is headless, or if not remote is defined, it will throw an exception It uses the "origin" remote if it exists, otherwise it uses the first remote available. If the remote requires authentication, a tuple of (username,password) must be passed in the credentials parameter ''' if (branch == geogig.HEAD and self.isdetached()): raise GeoGigException( "Cannot use current branch. The repository has a detached HEAD" ) remotes = self.remotes if remotes: if "origin" in remotes: remote = remotes["origin"] remotename = "origin" else: remotename = remotes.keys()[0] remote = remotes.values()[0] else: raise GeoGigException("No remotes defined") if isremoteurl(remote): repo = Repository(remote, GeoGigServerConnector(credentials)) else: conn = self.connector.__class__() repo = Repository(remote[len("file:/"):], conn) localtip = self.revparse(branch) remotetip = repo.revparse(branch) if remotetip == localtip: return 0, 0 if remotetip == geogig.NULL_ID: log = self.log(branch) push = len(log) pull = 0 else: trackedbranchhead = self.revparse("refs/remotes/" + remotename + "/" + branch) log = self.log(branch, trackedbranchhead) push = len(log) log = repo.log(branch, trackedbranchhead) pull = len(log) return push, pull
def revparse(self, rev): commands = ['rev-parse', rev] output = self.run(commands) id = output[0].strip() if len(id) != 40: raise GeoGigException("Cannot resolve the provided reference") return id
def setascurrent(self): '''Sets this version of the feature as the current one in the working tree and index''' if self.exists(): self.repo.updatepathtoref(self.ref, [self.path]) else: raise GeoGigException( "Feature at the specified path does not exist")
def query(self): data = self.repo.featuredata(self.ref, self.path) if len(data) == 0: raise GeoGigException( "Feature at the specified path does not exist") self._attributes = dict(((k, v[0]) for k, v in data.iteritems())) self._featuretype = dict(((k, v[1]) for k, v in data.iteritems()))
def _runGateway(_commands, url, addcolor = True): commands = list(_commands) gc.collect() if addcolor: commands.extend(["--color", "never"]) command = " ".join(commands) command = command.replace("\r", "") strclass = _javaGateway().jvm.String array = _javaGateway().new_array(strclass,len(commands)) for i, c in enumerate(commands): array[i] = c start = time.clock() returncode = _javaGateway().entry_point.runCommand(url, array) end = time.clock() diff = end - start _logger.debug("Executed " + hidePassword(command) + " in " + str(diff) + " millisecs") output = [""] page = _javaGateway().entry_point.nextOutputPage() while page is not None: output.append(page) page = _javaGateway().entry_point.nextOutputPage() output = "".join(output) output = output.strip("\r\n").splitlines() output = [s.strip("\r\n") for s in output] if returncode: errormsg = "\n".join(output) _logger.error("Error running command '%s': %s" % (hidePassword(command), errormsg)) raise GeoGigException("\n".join(output)) return output
def revparse(self, rev): try: url = self.repo.url + '/refparse' r = requests.get(url, params={'name': rev}, auth=self.credentials) root = ET.fromstring(r.text) id = root.iter('objectId').next().text return id except Exception, e: raise GeoGigException("Reference %s not found" % rev)
def commitatdate(self, t): '''Returns a Commit corresponding to a given instant, which is passed as a datetime.datetime''' epoch = datetime.datetime.utcfromtimestamp(0) delta = t - epoch milisecs = int(delta.total_seconds()) * 1000 log = self.connector.log(geogig.HEAD, until = str(milisecs), n = 1) if log: return log[0] else: raise GeoGigException("Invalid date for this repository")
def featuredata(self, ref, path): ''' Returns the attributes of a given feature, as a dict with attributes names as keys and tuples of (attribute_value, attribute_type_name) as values. Values are converted to appropriate types when possible, otherwise they are stored as the string representation of the attribute ''' data = self.connector.featuredata(_resolveref(ref), path) if len(data) == 0: raise GeoGigException("The specified feature does not exist") return data
def push(self, remote, branch = None, all = False): ''' Pushes to the specified remote and specified branch. If no branch is provided, it will use the name of the current branch, unless the repo is headless. In that case, and exception will be raised. if all == True, it will push all branches and ignore the branch. ''' if branch is None and self.isdetached(): raise GeoGigException("HEAD is detached. Cannot push") branch = branch or self.head.ref return self.connector.push(remote, branch, all)
def pull(self, remote = geogig.ORIGIN, branch = None, rebase = False): ''' Pulls from the specified remote and specified branch. If no branch is provided, it will use the name of the current branch, unless the repo is headless. In that case, and exception will be raised If rebase == True, it will do a rebase instead of a merge ''' if branch == None and self.isdetached(): raise GeoGigException("HEAD is detached. Cannot pull") branch = branch or self.head.ref self.connector.pull(remote, branch, rebase) self.cleancache()
def solveconflicts(self, paths, version=geogig.OURS): commands = ["checkout"] if version == geogig.OURS: commands.append("--ours") elif version == geogig.THEIRS: commands.append("--theirs") else: raise GeoGigException("Unknown option:" + version) commands.append("-p") commands.extend(paths) self.run(commands) self.add(paths)
def geomfieldname(self): ''' Returns the name of the geometry field of this feature. It assumes that the feature contains one and only one geometry. If there is no geometry, an exception is raised. If there are several of them, the first one found is returned. ''' attrs = self.attributes for k, v in attrs.iteritems(): if isinstance(v, Geometry): return k raise GeoGigException("Feature has no geometry")
def __init__(self, url, connector = None, init = False, initParams = None): ''' url: The url of the repository. Only file paths are supported so far. Remote repos are not supported connector: the connector to use to communicate with the repository init: True if the repository should be initialized ''' self.url = url self.connector = Py4JCLIConnector() if connector is None else connector if init: try: mkdir(url) except Exception, e: raise GeoGigException("Cannot create repository folder.\nCheck that path is correct and you have permission")
def _run(command, addcolor=True): command = ['geogig'] + command if addcolor: command.extend(["--color", "never"]) commandstr = " ".join(command) if os.name != 'nt': command = commandstr output = [] proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) for line in iter(proc.stdout.readline, ""): line = line.strip("\n") output.append(line) proc.wait() returncode = proc.returncode if returncode: logging.error("Error running " + commandstr + "\n" + " ".join(output)) raise GeoGigException(output) logging.info("Executed " + commandstr + "\n" + " ".join(output[:5])) return output
def diff(self, feature): if feature.path != self.path: raise GeoGigException("Cannot compare feature with different path") return self.repo.featurediff(self.ref, feature.ref, self.path)
def continue_(self): if self.isrebasing(): commands = ["rebase", "--continue"] self.run(commands) if self.isrebasing(): raise GeoGigException("Could not continue rebasing")
if init: try: mkdir(url) except Exception, e: raise GeoGigException("Cannot create repository folder.\nCheck that path is correct and you have permission") self.connector.setRepository(self) try: self.connector.checkisrepo() isAlreadyRepo = True except GeoGigException, e: isAlreadyRepo = False if init: if isAlreadyRepo: raise GeoGigException("Cannot init, the folder is already a geogig repository") else: self.init(initParams) self.connector.checkisrepo() self.cleancache() @staticmethod def newrepofromclone(url, path, connector = None, username = None, password = None): ''' Clones a given repository into a local folder and returns a repository object representing it url: the url of the repo to clone path: the path to clone the repo into
def checkisrepo(self): if not os.path.exists(os.path.join(self.repo.url, '.geogig')): raise GeoGigException("Not a valid GeoGig repository: " + self.repo.url)