mercurial/cext/revlog.c
changeset 45131 61e7464477ac
parent 44587 090a1a78be4a
child 45141 9719e118e4af
equal deleted inserted replaced
45130:33524b6bef53 45131:61e7464477ac
   107 static const char nullid[20] = {0};
   107 static const char nullid[20] = {0};
   108 static const Py_ssize_t nullrev = -1;
   108 static const Py_ssize_t nullrev = -1;
   109 
   109 
   110 static Py_ssize_t inline_scan(indexObject *self, const char **offsets);
   110 static Py_ssize_t inline_scan(indexObject *self, const char **offsets);
   111 
   111 
       
   112 static int index_find_node(indexObject *self, const char *node,
       
   113                            Py_ssize_t nodelen);
       
   114 
   112 #if LONG_MAX == 0x7fffffffL
   115 #if LONG_MAX == 0x7fffffffL
   113 static const char *const tuple_format = PY23("Kiiiiiis#", "Kiiiiiiy#");
   116 static const char *const tuple_format = PY23("Kiiiiiis#", "Kiiiiiiy#");
   114 #else
   117 #else
   115 static const char *const tuple_format = PY23("kiiiiiis#", "kiiiiiiy#");
   118 static const char *const tuple_format = PY23("kiiiiiis#", "kiiiiiiy#");
   116 #endif
   119 #endif
   573 		Py_DECREF(result);
   576 		Py_DECREF(result);
   574 		return isfiltered;
   577 		return isfiltered;
   575 	} else {
   578 	} else {
   576 		return 0;
   579 		return 0;
   577 	}
   580 	}
   578 }
       
   579 
       
   580 static Py_ssize_t add_roots_get_min(indexObject *self, PyObject *list,
       
   581                                     Py_ssize_t marker, char *phases)
       
   582 {
       
   583 	PyObject *iter = NULL;
       
   584 	PyObject *iter_item = NULL;
       
   585 	Py_ssize_t min_idx = index_length(self) + 2;
       
   586 	long iter_item_long;
       
   587 
       
   588 	if (PyList_GET_SIZE(list) != 0) {
       
   589 		iter = PyObject_GetIter(list);
       
   590 		if (iter == NULL)
       
   591 			return -2;
       
   592 		while ((iter_item = PyIter_Next(iter))) {
       
   593 			if (!pylong_to_long(iter_item, &iter_item_long)) {
       
   594 				Py_DECREF(iter_item);
       
   595 				return -2;
       
   596 			}
       
   597 			Py_DECREF(iter_item);
       
   598 			if (iter_item_long < min_idx)
       
   599 				min_idx = iter_item_long;
       
   600 			phases[iter_item_long] = (char)marker;
       
   601 		}
       
   602 		Py_DECREF(iter);
       
   603 	}
       
   604 
       
   605 	return min_idx;
       
   606 }
   581 }
   607 
   582 
   608 static inline void set_phase_from_parents(char *phases, int parent_1,
   583 static inline void set_phase_from_parents(char *phases, int parent_1,
   609                                           int parent_2, Py_ssize_t i)
   584                                           int parent_2, Py_ssize_t i)
   610 {
   585 {
   771 	free(revstates);
   746 	free(revstates);
   772 	free(tovisit);
   747 	free(tovisit);
   773 	return NULL;
   748 	return NULL;
   774 }
   749 }
   775 
   750 
       
   751 static int add_roots_get_min(indexObject *self, PyObject *roots, char *phases,
       
   752                              char phase)
       
   753 {
       
   754 	Py_ssize_t len = index_length(self);
       
   755 	PyObject *iter;
       
   756 	PyObject *item;
       
   757 	PyObject *iterator;
       
   758 	int rev, minrev = -1;
       
   759 	char *node;
       
   760 
       
   761 	if (!PySet_Check(roots))
       
   762 		return -2;
       
   763 	iterator = PyObject_GetIter(roots);
       
   764 	if (iterator == NULL)
       
   765 		return -2;
       
   766 	while ((item = PyIter_Next(iterator))) {
       
   767 		if (node_check(item, &node) == -1)
       
   768 			goto failed;
       
   769 		rev = index_find_node(self, node, 20);
       
   770 		/* null is implicitly public, so negative is invalid */
       
   771 		if (rev < 0 || rev >= len)
       
   772 			goto failed;
       
   773 		phases[rev] = phase;
       
   774 		if (minrev == -1 || minrev > rev)
       
   775 			minrev = rev;
       
   776 		Py_DECREF(item);
       
   777 	}
       
   778 	Py_DECREF(iterator);
       
   779 	return minrev;
       
   780 failed:
       
   781 	Py_DECREF(iterator);
       
   782 	Py_DECREF(item);
       
   783 	return -2;
       
   784 }
       
   785 
   776 static PyObject *compute_phases_map_sets(indexObject *self, PyObject *args)
   786 static PyObject *compute_phases_map_sets(indexObject *self, PyObject *args)
   777 {
   787 {
       
   788 	/* 0: public (untracked), 1: draft, 2: secret, 32: archive,
       
   789 	   96: internal */
       
   790 	static const char trackedphases[] = {1, 2, 32, 96};
       
   791 	PyObject *ret = NULL;
   778 	PyObject *roots = Py_None;
   792 	PyObject *roots = Py_None;
   779 	PyObject *ret = NULL;
   793 	PyObject *idx = NULL;
       
   794 	PyObject *pyphase = NULL;
       
   795 	PyObject *pyrev = NULL;
       
   796 	PyObject *phaseroots = NULL;
   780 	PyObject *phasessize = NULL;
   797 	PyObject *phasessize = NULL;
   781 	PyObject *phaseroots = NULL;
   798 	PyObject *phasesets[4] = {NULL, NULL, NULL, NULL};
   782 	PyObject *phaseset = NULL;
       
   783 	PyObject *phasessetlist = NULL;
       
   784 	PyObject *rev = NULL;
       
   785 	Py_ssize_t len = index_length(self);
   799 	Py_ssize_t len = index_length(self);
   786 	Py_ssize_t numphase = 0;
   800 	const char *currentphase;
   787 	Py_ssize_t minrevallphases = 0;
       
   788 	Py_ssize_t minrevphase = 0;
       
   789 	Py_ssize_t i = 0;
       
   790 	char *phases = NULL;
   801 	char *phases = NULL;
   791 	long phase;
   802 	int minphaserev = -1, rev, i;
       
   803 	const int numphases = (int)(sizeof(phasesets) / sizeof(phasesets[0]));
   792 
   804 
   793 	if (!PyArg_ParseTuple(args, "O", &roots))
   805 	if (!PyArg_ParseTuple(args, "O", &roots))
   794 		goto done;
   806 		return NULL;
   795 	if (roots == NULL || !PyList_Check(roots)) {
   807 	if (roots == NULL || !PyDict_Check(roots)) {
   796 		PyErr_SetString(PyExc_TypeError, "roots must be a list");
   808 		PyErr_SetString(PyExc_TypeError, "roots must be a dictionary");
   797 		goto done;
   809 		return NULL;
   798 	}
   810 	}
   799 
   811 
   800 	phases = calloc(
   812 	phases = calloc(len, 1);
   801 	    len, 1); /* phase per rev: {0: public, 1: draft, 2: secret} */
       
   802 	if (phases == NULL) {
   813 	if (phases == NULL) {
   803 		PyErr_NoMemory();
   814 		PyErr_NoMemory();
   804 		goto done;
   815 		return NULL;
   805 	}
   816 	}
   806 	/* Put the phase information of all the roots in phases */
   817 
   807 	numphase = PyList_GET_SIZE(roots) + 1;
   818 	for (i = 0; i < numphases; ++i) {
   808 	minrevallphases = len + 1;
   819 		pyphase = PyInt_FromLong(trackedphases[i]);
   809 	phasessetlist = PyList_New(numphase);
   820 		if (pyphase == NULL)
   810 	if (phasessetlist == NULL)
       
   811 		goto done;
       
   812 
       
   813 	PyList_SET_ITEM(phasessetlist, 0, Py_None);
       
   814 	Py_INCREF(Py_None);
       
   815 
       
   816 	for (i = 0; i < numphase - 1; i++) {
       
   817 		phaseroots = PyList_GET_ITEM(roots, i);
       
   818 		phaseset = PySet_New(NULL);
       
   819 		if (phaseset == NULL)
       
   820 			goto release;
   821 			goto release;
   821 		PyList_SET_ITEM(phasessetlist, i + 1, phaseset);
   822 		phaseroots = PyDict_GetItem(roots, pyphase);
   822 		if (!PyList_Check(phaseroots)) {
   823 		Py_DECREF(pyphase);
   823 			PyErr_SetString(PyExc_TypeError,
   824 		if (phaseroots == NULL)
   824 			                "roots item must be a list");
   825 			continue;
       
   826 		rev = add_roots_get_min(self, phaseroots, phases, trackedphases[i]);
       
   827 		phaseroots = NULL;
       
   828 		if (rev == -2)
   825 			goto release;
   829 			goto release;
   826 		}
   830 		if (rev != -1 && (minphaserev == -1 || rev < minphaserev))
   827 		minrevphase =
   831 			minphaserev = rev;
   828 		    add_roots_get_min(self, phaseroots, i + 1, phases);
   832 	}
   829 		if (minrevphase == -2) /* Error from add_roots_get_min */
   833 
       
   834 	for (i = 0; i < numphases; ++i) {
       
   835 		phasesets[i] = PySet_New(NULL);
       
   836 		if (phasesets[i] == NULL)
   830 			goto release;
   837 			goto release;
   831 		minrevallphases = MIN(minrevallphases, minrevphase);
   838 	}
   832 	}
   839 
   833 	/* Propagate the phase information from the roots to the revs */
   840 	if (minphaserev == -1)
   834 	if (minrevallphases != -1) {
   841 		minphaserev = len;
       
   842 	for (rev = minphaserev; rev < len; ++rev) {
   835 		int parents[2];
   843 		int parents[2];
   836 		for (i = minrevallphases; i < len; i++) {
   844 		/*
   837 			if (index_get_parents(self, i, parents, (int)len - 1) <
   845 		 * The parent lookup could be skipped for phaseroots, but
   838 			    0)
   846 		 * phase --force would historically not recompute them
   839 				goto release;
   847 		 * correctly, leaving descendents with a lower phase around.
   840 			set_phase_from_parents(phases, parents[0], parents[1],
   848 		 * As such, unconditionally recompute the phase.
   841 			                       i);
   849 		 */
   842 		}
   850 		if (index_get_parents(self, rev, parents, (int)len - 1) < 0)
   843 	}
   851 			goto release;
   844 	/* Transform phase list to a python list */
   852 		set_phase_from_parents(phases, parents[0], parents[1], rev);
       
   853 		switch (phases[rev]) {
       
   854 		case 0:
       
   855 			continue;
       
   856 		case 1:
       
   857 			pyphase = phasesets[0];
       
   858 			break;
       
   859 		case 2:
       
   860 			pyphase = phasesets[1];
       
   861 			break;
       
   862 		case 32:
       
   863 			pyphase = phasesets[2];
       
   864 			break;
       
   865 		case 96:
       
   866 			pyphase = phasesets[3];
       
   867 			break;
       
   868 		default:
       
   869 			goto release;
       
   870 		}
       
   871 		pyrev = PyInt_FromLong(rev);
       
   872 		if (pyrev == NULL)
       
   873 			goto release;
       
   874 		if (PySet_Add(pyphase, pyrev) == -1) {
       
   875 			Py_DECREF(pyrev);
       
   876 			goto release;
       
   877 		}
       
   878 		Py_DECREF(pyrev);
       
   879 	}
       
   880 	phaseroots = _dict_new_presized(numphases);
       
   881 	if (phaseroots == NULL)
       
   882 		goto release;
       
   883 	for (int i = 0; i < numphases; ++i) {
       
   884 		pyphase = PyInt_FromLong(trackedphases[i]);
       
   885 		if (pyphase == NULL)
       
   886 			goto release;
       
   887 		if (PyDict_SetItem(phaseroots, pyphase, phasesets[i]) == -1) {
       
   888 			Py_DECREF(pyphase);
       
   889 			goto release;
       
   890 		}
       
   891 		Py_DECREF(phasesets[i]);
       
   892 		phasesets[i] = NULL;
       
   893 	}
   845 	phasessize = PyInt_FromSsize_t(len);
   894 	phasessize = PyInt_FromSsize_t(len);
   846 	if (phasessize == NULL)
   895 	if (phasessize == NULL)
   847 		goto release;
   896 		goto release;
   848 	for (i = 0; i < len; i++) {
   897 
   849 		phase = phases[i];
   898 	ret = PyTuple_Pack(2, phasessize, phaseroots);
   850 		/* We only store the sets of phase for non public phase, the
   899 	Py_DECREF(phasessize);
   851 		 * public phase is computed as a difference */
   900 	Py_DECREF(phaseroots);
   852 		if (phase != 0) {
   901 	return ret;
   853 			phaseset = PyList_GET_ITEM(phasessetlist, phase);
       
   854 			rev = PyInt_FromSsize_t(i);
       
   855 			if (rev == NULL)
       
   856 				goto release;
       
   857 			PySet_Add(phaseset, rev);
       
   858 			Py_XDECREF(rev);
       
   859 		}
       
   860 	}
       
   861 	ret = PyTuple_Pack(2, phasessize, phasessetlist);
       
   862 
   902 
   863 release:
   903 release:
   864 	Py_XDECREF(phasessize);
   904 	for (i = 0; i < numphases; ++i)
   865 	Py_XDECREF(phasessetlist);
   905 		Py_XDECREF(phasesets[i]);
   866 done:
   906 	Py_XDECREF(phaseroots);
       
   907 
   867 	free(phases);
   908 	free(phases);
   868 	return ret;
   909 	return NULL;
   869 }
   910 }
   870 
   911 
   871 static PyObject *index_headrevs(indexObject *self, PyObject *args)
   912 static PyObject *index_headrevs(indexObject *self, PyObject *args)
   872 {
   913 {
   873 	Py_ssize_t i, j, len;
   914 	Py_ssize_t i, j, len;