124 break; |
124 break; |
125 case DH: |
125 case DH: |
126 if (src[i] == 'g') { |
126 if (src[i] == 'g') { |
127 state = DHGDI; |
127 state = DHGDI; |
128 charcopy(dest, &destlen, destsize, src[i++]); |
128 charcopy(dest, &destlen, destsize, src[i++]); |
129 } else |
129 } else { |
130 state = DDEFAULT; |
130 state = DDEFAULT; |
|
131 } |
131 break; |
132 break; |
132 case DHGDI: |
133 case DHGDI: |
133 if (src[i] == '/') { |
134 if (src[i] == '/') { |
134 memcopy(dest, &destlen, destsize, ".hg", 3); |
135 memcopy(dest, &destlen, destsize, ".hg", 3); |
135 charcopy(dest, &destlen, destsize, src[i++]); |
136 charcopy(dest, &destlen, destsize, src[i++]); |
136 } |
137 } |
137 state = DDEFAULT; |
138 state = DDEFAULT; |
138 break; |
139 break; |
139 case DDEFAULT: |
140 case DDEFAULT: |
140 if (src[i] == '.') |
141 if (src[i] == '.') { |
141 state = DDOT; |
142 state = DDOT; |
|
143 } |
142 charcopy(dest, &destlen, destsize, src[i++]); |
144 charcopy(dest, &destlen, destsize, src[i++]); |
143 break; |
145 break; |
144 } |
146 } |
145 } |
147 } |
146 |
148 |
496 static const uint32_t lower[8] = {0, 0, 0x7fffffe}; |
514 static const uint32_t lower[8] = {0, 0, 0x7fffffe}; |
497 |
515 |
498 Py_ssize_t i, destlen = 0; |
516 Py_ssize_t i, destlen = 0; |
499 |
517 |
500 for (i = 0; i < len; i++) { |
518 for (i = 0; i < len; i++) { |
501 if (inset(onebyte, src[i])) |
519 if (inset(onebyte, src[i])) { |
502 charcopy(dest, &destlen, destsize, src[i]); |
520 charcopy(dest, &destlen, destsize, src[i]); |
503 else if (inset(lower, src[i])) |
521 } else if (inset(lower, src[i])) { |
504 charcopy(dest, &destlen, destsize, src[i] + 32); |
522 charcopy(dest, &destlen, destsize, src[i] + 32); |
505 else |
523 } else { |
506 escape3(dest, &destlen, destsize, src[i]); |
524 escape3(dest, &destlen, destsize, src[i]); |
|
525 } |
507 } |
526 } |
508 |
527 |
509 return destlen; |
528 return destlen; |
510 } |
529 } |
511 |
530 |
514 char *path; |
533 char *path; |
515 Py_ssize_t len, newlen; |
534 Py_ssize_t len, newlen; |
516 PyObject *ret; |
535 PyObject *ret; |
517 |
536 |
518 if (!PyArg_ParseTuple(args, PY23("s#:lowerencode", "y#:lowerencode"), |
537 if (!PyArg_ParseTuple(args, PY23("s#:lowerencode", "y#:lowerencode"), |
519 &path, &len)) |
538 &path, &len)) { |
520 return NULL; |
539 return NULL; |
|
540 } |
521 |
541 |
522 newlen = _lowerencode(NULL, 0, path, len); |
542 newlen = _lowerencode(NULL, 0, path, len); |
523 ret = PyBytes_FromStringAndSize(NULL, newlen); |
543 ret = PyBytes_FromStringAndSize(NULL, newlen); |
524 if (ret) |
544 if (ret) { |
525 _lowerencode(PyBytes_AS_STRING(ret), newlen, path, len); |
545 _lowerencode(PyBytes_AS_STRING(ret), newlen, path, len); |
|
546 } |
526 |
547 |
527 return ret; |
548 return ret; |
528 } |
549 } |
529 |
550 |
530 /* See store.py:_auxencode for a description. */ |
551 /* See store.py:_auxencode for a description. */ |
568 #endif |
590 #endif |
569 |
591 |
570 /* If src contains a suffix, we will append it to the end of |
592 /* If src contains a suffix, we will append it to the end of |
571 the new string, so make room. */ |
593 the new string, so make room. */ |
572 destsize = 120; |
594 destsize = 120; |
573 if (lastdot >= 0) |
595 if (lastdot >= 0) { |
574 destsize += len - lastdot - 1; |
596 destsize += len - lastdot - 1; |
|
597 } |
575 |
598 |
576 ret = PyBytes_FromStringAndSize(NULL, destsize); |
599 ret = PyBytes_FromStringAndSize(NULL, destsize); |
577 if (ret == NULL) |
600 if (ret == NULL) { |
578 return NULL; |
601 return NULL; |
|
602 } |
579 |
603 |
580 dest = PyBytes_AS_STRING(ret); |
604 dest = PyBytes_AS_STRING(ret); |
581 memcopy(dest, &destlen, destsize, "dh/", 3); |
605 memcopy(dest, &destlen, destsize, "dh/", 3); |
582 |
606 |
583 /* Copy up to dirprefixlen bytes of each path component, up to |
607 /* Copy up to dirprefixlen bytes of each path component, up to |
585 for (i = d = p = 0; i < lastslash; i++, p++) { |
609 for (i = d = p = 0; i < lastslash; i++, p++) { |
586 if (src[i] == '/') { |
610 if (src[i] == '/') { |
587 char d = dest[destlen - 1]; |
611 char d = dest[destlen - 1]; |
588 /* After truncation, a directory name may end |
612 /* After truncation, a directory name may end |
589 in a space or dot, which are unportable. */ |
613 in a space or dot, which are unportable. */ |
590 if (d == '.' || d == ' ') |
614 if (d == '.' || d == ' ') { |
591 dest[destlen - 1] = '_'; |
615 dest[destlen - 1] = '_'; |
592 /* The + 3 is to account for "dh/" in the beginning */ |
616 /* The + 3 is to account for "dh/" in the |
593 if (destlen > maxshortdirslen + 3) |
617 * beginning */ |
594 break; |
618 } |
|
619 if (destlen > maxshortdirslen + 3) { |
|
620 break; |
|
621 } |
595 charcopy(dest, &destlen, destsize, src[i]); |
622 charcopy(dest, &destlen, destsize, src[i]); |
596 p = -1; |
623 p = -1; |
597 } else if (p < dirprefixlen) |
624 } else if (p < dirprefixlen) { |
598 charcopy(dest, &destlen, destsize, src[i]); |
625 charcopy(dest, &destlen, destsize, src[i]); |
|
626 } |
599 } |
627 } |
600 |
628 |
601 /* Rewind to just before the last slash copied. */ |
629 /* Rewind to just before the last slash copied. */ |
602 if (destlen > maxshortdirslen + 3) |
630 if (destlen > maxshortdirslen + 3) { |
603 do { |
631 do { |
604 destlen--; |
632 destlen--; |
605 } while (destlen > 0 && dest[destlen] != '/'); |
633 } while (destlen > 0 && dest[destlen] != '/'); |
|
634 } |
606 |
635 |
607 if (destlen > 3) { |
636 if (destlen > 3) { |
608 if (lastslash > 0) { |
637 if (lastslash > 0) { |
609 char d = dest[destlen - 1]; |
638 char d = dest[destlen - 1]; |
610 /* The last directory component may be |
639 /* The last directory component may be |
611 truncated, so make it safe. */ |
640 truncated, so make it safe. */ |
612 if (d == '.' || d == ' ') |
641 if (d == '.' || d == ' ') { |
613 dest[destlen - 1] = '_'; |
642 dest[destlen - 1] = '_'; |
|
643 } |
614 } |
644 } |
615 |
645 |
616 charcopy(dest, &destlen, destsize, '/'); |
646 charcopy(dest, &destlen, destsize, '/'); |
617 } |
647 } |
618 |
648 |
619 /* Add a prefix of the original file's name. Its length |
649 /* Add a prefix of the original file's name. Its length |
620 depends on the number of bytes left after accounting for |
650 depends on the number of bytes left after accounting for |
621 hash and suffix. */ |
651 hash and suffix. */ |
622 used = destlen + 40; |
652 used = destlen + 40; |
623 if (lastdot >= 0) |
653 if (lastdot >= 0) { |
624 used += len - lastdot - 1; |
654 used += len - lastdot - 1; |
|
655 } |
625 slop = maxstorepathlen - used; |
656 slop = maxstorepathlen - used; |
626 if (slop > 0) { |
657 if (slop > 0) { |
627 Py_ssize_t basenamelen = |
658 Py_ssize_t basenamelen = |
628 lastslash >= 0 ? len - lastslash - 2 : len - 1; |
659 lastslash >= 0 ? len - lastslash - 2 : len - 1; |
629 |
660 |
630 if (basenamelen > slop) |
661 if (basenamelen > slop) { |
631 basenamelen = slop; |
662 basenamelen = slop; |
632 if (basenamelen > 0) |
663 } |
|
664 if (basenamelen > 0) { |
633 memcopy(dest, &destlen, destsize, &src[lastslash + 1], |
665 memcopy(dest, &destlen, destsize, &src[lastslash + 1], |
634 basenamelen); |
666 basenamelen); |
|
667 } |
635 } |
668 } |
636 |
669 |
637 /* Add hash and suffix. */ |
670 /* Add hash and suffix. */ |
638 for (i = 0; i < 20; i++) |
671 for (i = 0; i < 20; i++) { |
639 hexencode(dest, &destlen, destsize, sha[i]); |
672 hexencode(dest, &destlen, destsize, sha[i]); |
640 |
673 } |
641 if (lastdot >= 0) |
674 |
|
675 if (lastdot >= 0) { |
642 memcopy(dest, &destlen, destsize, &src[lastdot], |
676 memcopy(dest, &destlen, destsize, &src[lastdot], |
643 len - lastdot - 1); |
677 len - lastdot - 1); |
|
678 } |
644 |
679 |
645 assert(PyBytes_Check(ret)); |
680 assert(PyBytes_Check(ret)); |
646 Py_SIZE(ret) = destlen; |
681 Py_SIZE(ret) = destlen; |
647 |
682 |
648 return ret; |
683 return ret; |
675 } |
710 } |
676 } |
711 } |
677 |
712 |
678 shaobj = PyObject_CallFunction(shafunc, PY23("s#", "y#"), str, len); |
713 shaobj = PyObject_CallFunction(shafunc, PY23("s#", "y#"), str, len); |
679 |
714 |
680 if (shaobj == NULL) |
715 if (shaobj == NULL) { |
681 return -1; |
716 return -1; |
|
717 } |
682 |
718 |
683 hashobj = PyObject_CallMethod(shaobj, "digest", ""); |
719 hashobj = PyObject_CallMethod(shaobj, "digest", ""); |
684 Py_DECREF(shaobj); |
720 Py_DECREF(shaobj); |
685 if (hashobj == NULL) |
721 if (hashobj == NULL) { |
686 return -1; |
722 return -1; |
|
723 } |
687 |
724 |
688 if (!PyBytes_Check(hashobj) || PyBytes_GET_SIZE(hashobj) != 20) { |
725 if (!PyBytes_Check(hashobj) || PyBytes_GET_SIZE(hashobj) != 20) { |
689 PyErr_SetString(PyExc_TypeError, |
726 PyErr_SetString(PyExc_TypeError, |
690 "result of digest is not a 20-byte hash"); |
727 "result of digest is not a 20-byte hash"); |
691 Py_DECREF(hashobj); |
728 Py_DECREF(hashobj); |
712 PyErr_SetString(PyExc_ValueError, "string too long"); |
749 PyErr_SetString(PyExc_ValueError, "string too long"); |
713 return NULL; |
750 return NULL; |
714 } |
751 } |
715 |
752 |
716 dirlen = _encodedir(dired, baselen, src, len); |
753 dirlen = _encodedir(dired, baselen, src, len); |
717 if (sha1hash(sha, dired, dirlen - 1) == -1) |
754 if (sha1hash(sha, dired, dirlen - 1) == -1) { |
718 return NULL; |
755 return NULL; |
|
756 } |
719 lowerlen = _lowerencode(lowered, baselen, dired + 5, dirlen - 5); |
757 lowerlen = _lowerencode(lowered, baselen, dired + 5, dirlen - 5); |
720 auxlen = auxencode(auxed, baselen, lowered, lowerlen); |
758 auxlen = auxencode(auxed, baselen, lowered, lowerlen); |
721 return hashmangle(auxed, auxlen, sha); |
759 return hashmangle(auxed, auxlen, sha); |
722 } |
760 } |
723 |
761 |
725 { |
763 { |
726 Py_ssize_t len, newlen; |
764 Py_ssize_t len, newlen; |
727 PyObject *pathobj, *newobj; |
765 PyObject *pathobj, *newobj; |
728 char *path; |
766 char *path; |
729 |
767 |
730 if (!PyArg_ParseTuple(args, "O:pathencode", &pathobj)) |
768 if (!PyArg_ParseTuple(args, "O:pathencode", &pathobj)) { |
731 return NULL; |
769 return NULL; |
|
770 } |
732 |
771 |
733 if (PyBytes_AsStringAndSize(pathobj, &path, &len) == -1) { |
772 if (PyBytes_AsStringAndSize(pathobj, &path, &len) == -1) { |
734 PyErr_SetString(PyExc_TypeError, "expected a string"); |
773 PyErr_SetString(PyExc_TypeError, "expected a string"); |
735 return NULL; |
774 return NULL; |
736 } |
775 } |
737 |
776 |
738 if (len > maxstorepathlen) |
777 if (len > maxstorepathlen) { |
739 newlen = maxstorepathlen + 2; |
778 newlen = maxstorepathlen + 2; |
740 else |
779 } else { |
741 newlen = len ? basicencode(NULL, 0, path, len + 1) : 1; |
780 newlen = len ? basicencode(NULL, 0, path, len + 1) : 1; |
|
781 } |
742 |
782 |
743 if (newlen <= maxstorepathlen + 1) { |
783 if (newlen <= maxstorepathlen + 1) { |
744 if (newlen == len + 1) { |
784 if (newlen == len + 1) { |
745 Py_INCREF(pathobj); |
785 Py_INCREF(pathobj); |
746 return pathobj; |
786 return pathobj; |