DebugLog.log("collecting commitables for " + targetFile);
    public static SVNCommitItem[] harvestCommitables(SVNWCAccess baseAccess,            Collection paths, Map lockTokens, boolean justLocked,            boolean recursive, boolean force) throws SVNException {        Map commitables = new TreeMap();        Collection danglers = new HashSet();        Iterator targets = paths.iterator();        do {            String target = targets.hasNext() ? (String) targets.next() : "";            // get entry for target            File targetFile = new File(baseAccess.getAnchor().getRoot(), target);            String targetName = "".equals(target) ? "" : PathUtil.tail(target);            String parentPath = "".equals(target) ? "" : PathUtil                    .removeTail(target);            if (parentPath.startsWith("/")) {                parentPath = PathUtil.removeLeadingSlash(parentPath);            }            SVNDirectory dir = baseAccess.getDirectory(parentPath);            SVNEntry entry = dir == null ? null : dir.getEntries().getEntry(                    targetName, false);            String url = null;            if (entry == null) {                SVNErrorManager.error("svn: '" + targetFile + "' is not under version control");            } else if (entry.getURL() == null) {                SVNErrorManager.error("svn: '" + targetFile + "' has no URL");            } else {                url = entry.getURL();            }            if (entry != null                    && (entry.isScheduledForAddition() || entry                            .isScheduledForReplacement())) {                // get parent (for file or dir-> get ""), otherwise open parent                // dir and get "".                SVNEntry parentEntry;                if (!"".equals(targetName)) {                    parentEntry = dir.getEntries().getEntry("", false);                } else {                    File parentFile = targetFile.getParentFile();                    SVNWCAccess parentAccess = SVNWCAccess.create(parentFile);                    parentEntry = parentAccess.getTarget().getEntries()                            .getEntry("", false);                }                if (parentEntry == null) {                    SVNErrorManager                            .error("svn: '"                                    + targetFile                                    + "' is scheduled for addition within unversioned parent");                } else if (parentEntry.isScheduledForAddition()                        || parentEntry.isScheduledForReplacement()) {                    danglers.add(targetFile.getParentFile());                }            }            boolean recurse = recursive;            if (entry != null && entry.isCopied()                    && entry.getSchedule() == null) {                // if commit is forced => we could collect this entry, assuming                // that its parent is already included into commit                // it will be later removed from commit anyway.                if (!force) {                    SVNErrorManager                            .error("svn: Entry for '"                                    + targetFile                                    + "' is marked as 'copied' but is not itself scheduled\n"                                    + "for addition.  Perhaps you're committing a target that is\n"                                    + "inside an unversioned (or not-yet-versioned) directory?");                } else {                    // just do not process this item as in case of recursive                    // commit.                    continue;                }            } else if (entry != null && entry.isCopied()                    && entry.isScheduledForAddition()) {                if (force) {                    recurse = true;                }            } else if (entry != null && entry.isScheduledForDeletion()) {                if (force && !recursive) {                    // if parent is also deleted -> skip this entry                    SVNEntry parentEntry;                    if (!"".equals(targetName)) {                        parentEntry = dir.getEntries().getEntry("", false);                    } else {                        File parentFile = targetFile.getParentFile();                        SVNWCAccess parentAccess = SVNWCAccess.create(parentFile);                        parentEntry = parentAccess.getTarget().getEntries()                                .getEntry("", false);                    }                    if (parentEntry != null && parentEntry.isScheduledForDeletion() &&                            paths.contains(parentPath)) {                        continue;                    }                    recurse = true;                }            }            DebugLog.log("collecting commitables for " + targetFile);            harvestCommitables(commitables, dir, targetFile, null, entry, url,                    null, false, false, justLocked, lockTokens, recurse);        } while (targets.hasNext());        for (Iterator ds = danglers.iterator(); ds.hasNext();) {            File file = (File) ds.next();            if (!commitables.containsKey(file)) {                SVNErrorManager.error("svn: '" + file                        + "' is not under version control\n"                        + "and is not part of the commit, \n"                        + "yet its child is part of the commit");            }        }        return (SVNCommitItem[]) commitables.values().toArray(                new SVNCommitItem[commitables.values().size()]);    }