PageRenderTime 33ms CodeModel.GetById 18ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 1ms

/win32/shellext/DirectoryStatus.cpp

https://bitbucket.org/tortoisehg/hgtk/
C++ | 167 lines | 115 code | 38 blank | 14 comment | 29 complexity | cba733c49e134c0270164bf31e4e8747 MD5 | raw file
  1
  2// Copyright (C) 2009 Adrian Buehlmann
  3//
  4// This program is free software: you can redistribute it and/or modify
  5// it under the terms of the GNU General Public License as published by
  6// the Free Software Foundation, either version 2 of the License, or
  7// (at your option) any later version.
  8//
  9// This program is distributed in the hope that it will be useful,
 10// but WITHOUT ANY WARRANTY; without even the implied warranty of
 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12// GNU General Public License for more details.
 13//
 14// You should have received a copy of the GNU General Public License
 15// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 16
 17#include "stdafx.h"
 18
 19#include "DirectoryStatus.h"
 20#include "Thgstatus.h"
 21#include "TortoiseUtils.h"
 22
 23
 24char DirectoryStatus::status(const std::string& relpath_) const
 25{
 26    char res = 'C';
 27    bool added = false;
 28    bool modified = false;
 29
 30    const std::string relpath = relpath_ + '/';
 31
 32    for (V::const_iterator i = v_.begin(); i != v_.end(); ++i)
 33    {
 34        const E& e = *i;
 35        if (relpath_.empty() ||
 36            e.path_.compare(0, relpath.length(), relpath) == 0)
 37        {
 38            if (e.status_ == 'm' || e.status_ == 'r')
 39            {
 40                modified = true;
 41                break;
 42            }
 43            if (e.status_ == 'a')
 44                added = true;
 45        }
 46    }
 47
 48    if (modified)
 49        res = 'M';
 50    else if (added)
 51        res = 'A';
 52    else
 53        res = 'C';
 54
 55    return res;
 56}
 57
 58
 59int DirectoryStatus::read(const std::string& hgroot, const std::string& cwd)
 60{
 61    v_.clear();
 62    noicons_ = false;
 63
 64    std::string p = hgroot + "\\.hg\\thgstatus";
 65
 66    FILE *f = fopenReadRenameAllowed(p.c_str());
 67    if (!f)
 68    {
 69        TDEBUG_TRACE("DirectoryStatus::read: can't open '" << p << "'");
 70        std::string p = (cwd.size() < hgroot.size() ? hgroot : cwd);
 71        Thgstatus::update(p);
 72        return 0;
 73    }
 74
 75    DirectoryStatus::E e;
 76
 77    int res = 1;
 78    const std::string noicons = "@@noicons";
 79
 80    std::vector<char> vline(200);
 81
 82    for (;;)
 83    {
 84        vline.clear();
 85        char t;
 86
 87        for (;;)
 88        {
 89            if (fread(&t, sizeof(t), 1, f) != 1)
 90                goto close;
 91            if (t == '\n')
 92                break;
 93            vline.push_back(t);
 94            if (vline.size() > 1000)
 95            {
 96                res = 0;
 97                goto close;
 98            }
 99        }
100        vline.push_back(0);
101
102        std::string line = &vline[0];
103
104        if (line.substr(0, noicons.size()) == noicons)
105        {
106            noicons_ = true;
107            goto close;
108        }
109
110        if (line.empty())
111            goto close;
112
113        e.status_ = line[0];
114
115        std::string path;
116        if (line.size() > 1)
117        {
118            path = line.c_str() + 1;
119            ::CharLower(const_cast<char*>(path.c_str()));
120        }
121        path.push_back('/');
122
123        e.path_ = path;
124
125        v_.push_back(e);
126    }
127
128close:
129    fclose(f);
130
131    TDEBUG_TRACE("DirectoryStatus::read(" << hgroot << "): done. "
132        << v_.size() << " entries read. noicons_ = " << noicons_ );
133
134    return res;
135}
136
137
138struct CacheEntry
139{
140    std::string     hgroot_;
141    DirectoryStatus ds_;
142    bool            readfailed_;
143    unsigned        tickcount_;
144
145    CacheEntry(): readfailed_(false), tickcount_(0) {};
146};
147
148
149DirectoryStatus* DirectoryStatus::get(
150    const std::string& hgroot, const std::string& cwd)
151{
152    static CacheEntry ce;
153    
154    unsigned tc = GetTickCount();
155
156    if (ce.hgroot_ != hgroot || (tc - ce.tickcount_) > 2000)
157    {
158        ce.hgroot_.clear();
159        ce.readfailed_ = (ce.ds_.read(hgroot, cwd) == 0);
160        ce.hgroot_ = hgroot;
161        ce.tickcount_ = GetTickCount();
162    }
163
164    return (ce.readfailed_ ? 0 : &ce.ds_);
165}
166
167